Repository navigation
fix(jetstream): report CF's exact status for a 5xx - #6049
Merged
norman-abramovitz merged 3 commits intoOct 23, 2026
Merged
norman-abramovitz merged 3 commits into
norman-abramovitz merged 3 commits into
Conversation
The capi replace moves from fix/si-delete-204 (a3625ed) to the fork's stratos/integration branch (a4e9d75), which merges that fix with two more: - A CF 5xx that outlasts capi's retries used to come back as "giving up after N attempt(s)", with no sentinel and no envelope. It now maps through MapHTTPError like any other error response, so it keeps capi.ErrServerError and CF's v3 error envelope. - Every error MapHTTPError returns is a *capi.StatusError carrying the exact HTTP status. This change does not read it yet. With the first, the native handlers classify a persistent CF 5xx as unreachable and pass CF's envelope through. The associate-user test that pinned the old plain 502 with no reason now expects that. All seven Go modules are tidy.
upstreamStatusOf read the CF status from the "(status NNN)" text in capi's message, or from a sentinel that stands for one status. A CF v3 error envelope carries no "(status NNN)", and capi.ErrServerError and capi.ErrBadRequest each cover a range, so an envelope 5xx or other 4xx reported no status. The endpoint banner for a CF 5xx read "Request failed." with no code. It now reads *capi.StatusError first, which capi returns for every mapped error response. X-Stratos-Upstream-Status and the error body's upstreamStatus carry CF's code, and the banner reads "HTTP 503: The endpoint is unreachable or down.". The message and sentinel fallbacks stay for errors whose wrap chain no longer reaches the StatusError, such as the "no web process" error that wraps a bare capi.ErrNotFound. statusFromCapiError is unchanged: it picks the response status, which still answers a CF 5xx with 502.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a Cloud Foundry endpoint keeps answering with a server error (5xx), Stratos showed "Cloud Foundry endpoint '' / Request failed." with no status code. The capi client retried the 5xx and then returned "giving up after N attempt(s)", which carried no status, sentinel or error envelope, so Jetstream could not tell an endpoint fault from any other failure. With this change the banner reads "HTTP 503: The endpoint is unreachable or down." with Cloud Foundry's own code.
This follows #6047, which passed Cloud Foundry's 4xx statuses through. Its "Not in this PR" section named this case.
What changes
capi pin (
chore(deps): pin capi to the fork's integration branch)replaceforgithub.com/fivetwenty-io/capi/v3moves from the fork'sfix/si-delete-204branch (a3625ed, fix: treat a 204 service instance delete as done fivetwenty-io/capi#16) to itsstratos/integrationbranch (a4e9d75). That branch merges Adding app.model.modelManager #16 with two capi changes:MapHTTPErrorlike any other error response, so it keepscapi.ErrServerErrorand Cloud Foundry's v3 error envelope.MapHTTPErrorreturns is a*capi.StatusErrorthat carries the exact HTTP status. The change is additive: messages,errors.Ison the sentinels anderrors.Ason*capi.ResponseErrorbehave as before.unreachableand pass Cloud Foundry's envelope through. The associate-user test that pinned the old plain 502 with no reason now expects that.Exact status (
fix(jetstream): report CF's exact status for a 5xx)upstreamStatusOfreads*capi.StatusErrorfirst, soX-Stratos-Upstream-Statusand the error body'supstreamStatuscarry Cloud Foundry's code for an envelope 5xx and for a 4xx outside the single-status sentinels, such as a 400.StatusError. One example is the "no web process" error, which wraps a barecapi.ErrNotFound.statusFromCapiErroris unchanged. It sets the response status, which still answers a CF 5xx with 502.Tests
TestUpstreamStatusOfgains a 400 and a 503 envelope case built byMapHTTPError. Both failed before the status commit (they reported 0).TestAssociateUser_CFRejectionKeepsStatus, the "create server error" case runs the real capi client against a stub that answers 503 to every create attempt. It now expects a 502 with reasonunreachable, upstream status503and Cloud Foundry'sCF-ServerErrorenvelope. Before the bump it got a plain 502 with no reason and no status.make check gate: passed (4581 tests passed, 1 skipped). Go lint: 0 issues in all seven modules.Live checks
Against a Cloud Foundry lab. One registered endpoint pointed at a local proxy that forwards to the CF API and, while armed, answers every
GET /v3/spaceswith a real 503CF-ServerErrorenvelope, so the failure goes through Jetstream and capi's retries. Same DB and the same clicks, first with develop's backend, then with this branch's:The response status stays 502 in both, as intended; only the reason and the upstream status change.
Dependency note
The pin is a pseudo-version of a personal fork. The upstream fivetwenty-io/capi PR for the two new capi changes opens after this release, together with #16. The
replaceis dropped once a capi release carries all three.Release note:
changelog.d/0025-capi-5xx-status.md.AI disclosure (RFC-0047): prepared with AI coding assistance; reviewed by the author.