Skip to content

fix(error-handler): coerce apiContext->key to public_key string#85

Merged
kennethphough merged 1 commit into
masterfrom
fix/error-handler-api-key-modelobject
May 22, 2026
Merged

fix(error-handler): coerce apiContext->key to public_key string#85
kennethphough merged 1 commit into
masterfrom
fix/error-handler-api-key-modelobject

Conversation

@kennethphough

Copy link
Copy Markdown
Member

Summary

  • ErrorHandler crash that surfaced as blank HTTP 500s to clients since v4.4.0
  • Customer report: ETOM seeing 500s on routes that hit any exception, including /Session and /DoctorLensMarkup
  • Root cause: bare $this->apiContext->key (a ModelObject) bound into a string column → mysqli secondary fatal → original error swallowed
  • Fix: extract scalar public_key string for logging; falls back to null when ModelObject is unloaded

Why this slipped past tests

Pre-existing ErrorHandler tests set $context->key = null, so they never exercised the ModelObject path. Regression test added.

Test plan

  • New testApiContextKeyAsModelObjectLogsPublicKeyString creates a real KyteAPIKey ModelObject, sets it as context->key, calls handleException, asserts the row writes with api_key containing the public_key string
  • All 182 tests pass (181 existing + 1 new)
  • Other ErrorHandler tests confirm context->key = null path still works (no regression)

Rollout

Patch v4.4.2. No schema changes. Customer impact severe — needs to ship asap.

🤖 Generated with Claude Code

ErrorHandler::handleException()/handleError() bound $this->apiContext->key
directly into the KyteError.api_key string column. Api.php sets
$this->key = new ModelObject(KyteAPIKey) — so mysqli_stmt::execute()
threw "Object of class Kyte\Core\ModelObject could not be converted
to string" *inside* the error handler. The secondary fatal swallowed
the original error and surfaced to clients as a blank HTTP 500.

Pre-existing ErrorHandler tests set context->key = null, missing the
ModelObject path entirely. That's why the regression shipped in
v4.4.0 and v4.4.1.

Fix: extract the scalar public_key string for logging:
  'api_key' => isset($this->apiContext->key->public_key)
    ? (string)$this->apiContext->key->public_key : null

Falls back to null when ->key is unset or the ModelObject hasn't been
retrieved. public_key is the audit-relevant value the column was
designed to hold.

Regression test ErrorHandlerSensitivityTest::
testApiContextKeyAsModelObjectLogsPublicKeyString exercises the real
ModelObject path with a created KyteAPIKey fixture.

All 182 tests pass.

Patch-level fix. No schema changes. Composer update is sufficient.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kennethphough
kennethphough merged commit 5b79e5e into master May 22, 2026
4 checks passed
@kennethphough
kennethphough deleted the fix/error-handler-api-key-modelobject branch May 22, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant