Repository navigation
Conversation
A 400 from the Comms API was rethrown as a raw CommsRequestError, so the user saw a stack trace and never the server's reason. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
@doistbot /review |
doistbot
left a comment
There was a problem hiding this comment.
This PR extends wrapResult's error translation to cover 400 (INVALID_REQUEST), 429 (RATE_LIMITED), 5xx (API_ERROR) and no-response (NETWORK_ERROR) failures, mapping them onto CliErrors with the server's reason surfaced instead of a raw stack trace. No inline issues were flagged; the new branches were reviewed as cleanly following the existing central-translation pattern and ErrorCode conventions, correctly ordered after the more specific 401/403/404/409 mappings, with tests covering each new branch, the missing-error_string fallback, the unmapped-error fallthrough (updated to 418), and non-Comms errors passing through.
I also included a few optional follow-up notes in the details below.
Optional follow-up notes (2)
src/lib/api.ts:242: Reuse: errors.ts already centralizes status checks behind predicates built on
hasCommsStatusCode(isInsufficientScope, isForbidden, isInvalidToken, etc.), and this file imports those instead of touchinghttpStatusCodedirectly. Consider addingisRateLimited/isServerError/isBadRequest-style predicates there (usinghasCommsStatusCodeor taking the status) so the 400/429/5xx checks follow the same pattern and stay in one place for the next status mapping.src/lib/api.test.ts:354: All 5xx cases pass
{}as the SDK response, so none protect the stated decision that 5xx messages omit the server body (often proxy HTML). IfwrapResultlater includesgetCommsErrorString(error)in the 5xx message, these tests still pass. Add a 5xx case with a non-emptyerror_stringand assert that body is not part of the message.
Also pin that a 5xx message leaves out the server body. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Done in 89dec11. Added
Done in 89dec11. Added a 502 case with an |
An empty error_string produced a blank reason. Also derive the 5xx range from one shared status helper, unit-test the new predicates and the range edges, and correct the isNoResponse comment and error code ordering. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
@doistbot /review |
doistbot
left a comment
There was a problem hiding this comment.
This PR cleanly extends wrapResult's error translation so 400, 429, 5xx, and no-response failures surface as well-formed CliErrors instead of raw stack traces, with the new status predicates (built on the existing hasCommsStatusCode / range helper in errors.ts) correctly centralized alongside the established patterns and correct branch ordering. No inline issues were flagged. Tests cover each new mapping, the error_string fallback paths, the 5xx range edges, the deliberate omission of server bodies for 5xx messages, and pass-through for non-Comms and unmapped statuses, and a security-focused pass found no trust-boundary concerns — messages only interpolate the same SDK/server fields already used by the 403/404/409 branches.
I also left one optional follow-up note in the details below.
Optional follow-up note (1)
src/lib/api.test.ts:331: This standalone no-
error_stringcase overlaps with theit.eachbelow, which already exercises the samegetCommsErrorString(error) || '400 Bad Request'fallback for other unusable-body shapes ('',42,'not json'). Fold{}into thatit.eachas a fourth case and delete this test — the fallback path stays protected with one less test to maintain.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Done in d77d6c0. |
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Overview
wrapResultonly translated 401, 403, 404 and 409. Any other failure, notably a 400, reached the user as a rawCommsRequestErrorstack trace with the server'serror_stringdropped ({"error":{"code":"INTERNAL_ERROR","message":"Request failed with status 400"}}under--json). 429, 5xx and network-down took the same path. Found by an offline review of #77.These now map to
CliErrors, exit 1, parseable under--json:INVALID_REQUEST, with the server's reason as the messageRATE_LIMITEDAPI_ERROR(existing code)NETWORK_ERROR, with the SDK's message (which already carries the cause and retry count)Not in this PR: other 4xx statuses (413, 422 and so on) still pass through as before, and
tdc search/tdc mentionsuse their own fetch outside this path.The SDK has no predicates for these statuses, so the branches read
CommsRequestError.httpStatusCode. 5xx messages leave out the server body on purpose, since it is often proxy HTML.Reference
Found while reviewing #77. No flag.
Changelog
Bad requests, rate limits, server errors and network failures from the Comms API now show a clear message instead of a stack trace.
Test plan
main, point the CLI at a local server that answers every request with 400{"error_string": "Status message must be between 1 and 80 characters"}, then runCOMMS_API_TOKEN=x COMMS_BASE_URL=http://127.0.0.1:<port> tdc user.--jsongivesINTERNAL_ERROR.Comms rejected the request: Status message must be between 1 and 80 characters, exit 1.--json, the output parses anderror.codeisINVALID_REQUEST.RATE_LIMITEDandAPI_ERROR, each with a retry hint.NETWORK_ERROR, with the cause in the message.Adversarial review
89dec11🤖 Generated with Claude Code