Repository navigation
fix(auth): keep the real upstream reason in lastError - #11376
diegosouzapw merged 2 commits into
Conversation
`markAccountUnavailable` stored the reason only when it was already a string, so every other shape collapsed to the literal "Provider error" — the value the dashboard shows as `lastError` and the console line prints. The shape that matters most is not a string. A failed `fetch` arrives as `TypeError: fetch failed` with the actionable part on `error.cause.code`, so a wrong port, a firewall, a DNS failure and a blocked proxy were indistinguishable to the operator. `describeUpstreamFailure` reuses the `extractErrorMessage` already in `upstreamError.ts` (now exported) for provider JSON bodies, appends the transport code when the message does not carry it, and falls back to the code alone before giving up. It never serializes the error object wholesale, so a request body or header attached to an error cannot leak into the stored reason.
|
CI note, so the red is not left ambiguous.
The same assertion fails identically on #11374, #11376, #11377 and #11380, whose
I have not touched the coverage floor: rebaselining a gate I did not break is not |
`Fast Quality Gates` refused the file-size ratchet: `src/sse/services/auth.ts: 3346 > congelado 3344`. The two lines, itemised in the baseline entry: the import of `describeUpstreamFailure` (the logic itself lives in upstreamError.ts, so nothing else moved into this file, and the call site is net zero), and the repo's own lint-staged prettier pass splitting a pre-existing two-statements-on-one-line at `getProviderCredentials` — which re-applies on any commit touching this file, so it cannot be separated out.
|
CI update — all three reds are base-side; none are reachable from this diff.
Identical inputs cannot produce a different coverage number, so this PR cannot have moved it.
Nothing to change here. Happy to rebase if you want a fresh run. |
019ad33
into
cheaper-inference:release/v3.8.50
…nce#11376) Merged via consolidated batch validation. markAccountUnavailable collapsed every non-string upstream error reason to a generic 'Provider error' literal, hiding the actual upstream detail operators need in lastError. Own test passes.
release/v3.8.50is not green; the failures this PRinherits are the ones tracked there, not introduced here.
Problem
markAccountUnavailable(src/sse/services/auth.ts) kept the upstream reason onlywhen it was already a string:
Everything else collapsed to that literal, and it is what the operator reads —
lastErroron the connection row, and the❌ provider [status]: …console line.The shape that matters most is not a string. A failed
fetcharrives asTypeError: fetch failedwith the actionable part onerror.cause.code, so awrong port, a firewall, a DNS failure and a blocked proxy were indistinguishable
from each other and from a provider that simply said no.
Change
describeUpstreamFailure(value, fallback?, maxLength?)insrc/shared/utils/upstreamError.ts, next to the code that already parses providererror bodies. It reuses the module's
extractErrorMessage(now exported ratherthan duplicated) and adds what that helper does not cover:
Error's message, with the transport code appended when the message does notalready carry it —
fetch failed (ECONNREFUSED);Provider error (EAI_AGAIN);The value is never serialized wholesale. Only message-shaped fields and codes
are read, so a request body or header attached to an error cannot reach the stored
reason. A test attaches an
authorizationheader to the error and asserts it doesnot appear in the output.
Tests
tests/unit/provider-error-detail-lastError.test.ts(new, 10 cases): the stringpath unchanged including the 100-char clamp;
fetch failedwith ECONNREFUSED /ENOTFOUND; no duplicated code when the message already names it; the provider JSON
shapes including
errors[]; the code-only fallback and a custom fallback;{}/null/undefined/ a number; the no-wholesale-serialization guarantee; newlinecollapsing;
extractErrorMessagestill behaving for its existing caller; and asource assertion that
auth.tsroutes through the helper and that the string-onlycollapse is gone.
Without the source change the file cannot even resolve
describeUpstreamFailure,so it fails at import (
not ok 1 … # fail 1) rather than per-case — noted here sothe "fails on base" claim is not overstated.
npx tsc --noEmitclean;npx eslint --suppressions-location config/quality/eslint-suppressions.jsonclean on the changed files.
Changelog fragment:
changelog.d/fixes/lasterror-provider-error-detail.md.