fix(e2e): surface tenant_call HTTP body on non-2xx (no more opaque curl:22) #2310
Reference in New Issue
Block a user
Delete Branch "fix/e2e-tenant-call-surface-body"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Root cause
The staging e2e suites fail opaquely on a non-2xx workspace/org create. The
tenant_call/admin_callhelpers inheritCURL_COMMON=(-sS --fail-with-body --max-time 30). With--fail-with-body, curl on a 4xx/5xx writes the body to stdout and then exits 22. Captured bare asPARENT_RESP=$(tenant_call POST /workspaces ...), that exit 22 propagates through the command substitution and, under the script'sset -euo pipefail, aborts the whole script at the create line — before the existing nice handler:…ever runs. So the response body (the why) is never printed.
Evidence
Run 220702 (main
f78fef4c, job "E2E Staging SaaS") reached5/11 Provisioning parent workspacethen died with barecurl: (22) The requested URL returned error: 422and tore down — with no HTTP body, so the 422 detail was invisible.Fix (test-only — zero production code)
Wrap the create captures in
set +e ... set -e(the exact idiom this file already uses for the 409 optimistic-lock and shared-context-gone gates). curl still writes the body with--fail-with-body, so the response variable holds the error JSON and the existingfail "... Response: ..."/fail "... missing 'id'"handler runs and surfaces it.2xxbehavior is unchanged. The suite still FAILS on a 422 (it's a real red) — now with the body printed.Files
tests/e2e/test_staging_full_saas.sh— parent + child workspace createtests/e2e/test_staging_external_runtime.sh— org create + external workspace create (same--fail-with-bodyabort class; routed the twoid-missingfails throughsanitize_http_bodyso the now-surfaced body can't leak creds)Sibling suites
test_2307_peer_visibility_staging.shandtest_peer_visibility_mcp_staging.shuse plaincurl -sS(no--fail), so they don't have this bug and are untouched.Non-changes
No assertions or pass/fail semantics changed. No
continue-on-errorflipped, no workflow gating touched. No.go/ template / manifest changes.Verification
bash -nclean on both changed scripts.shellcheck -xclean ontest_staging_full_saas.sh(exit 0); the oneSC2015info intest_staging_external_runtime.sh:183is pre-existing on main, outside this diff.set -e, a--fail-with-body422 aborts the bare capture before the handler; with theset +eguard the body reaches thefailhandler and the script still exits RED, while the2xxpath returns the body and continues unchanged.🤖 Generated with Claude Code
APPROVED (CTO review). Verified diff: 2 tests/e2e files ONLY, zero prod code. Correct root cause — CURL_COMMON --fail-with-body makes curl exit 22 on non-2xx; under set -euo pipefail the bare $(tenant_call) capture aborts the script BEFORE the body-surfacing fail handler runs (run 220702: opaque curl:22 422 + teardown, no body). Fix is the right idiom: set +e/set -e scoped tightly around the create captures so the 422 body reaches the existing .get(id) check + fail; id-parse made set-e-safe with ||echo; missing-id fails routed through sanitize_http_body (cred-safe). No assertions/gating/continue-on-error changed — suite still RED on 422, now WITH the body. bash -n + shellcheck clean (lone SC2015 pre-existing). This makes the real-runtime regression guard debuggable. Approving.
APPROVED after 5-axis review on current head
0130f293c8.Correctness: the diff addresses the opaque curl 22 failure mode in the staging E2E create captures. Non-2xx bodies from
--fail-with-bodyare now retained so the existing missing-id fail handlers can surface useful response details.Robustness: only
tests/e2e/test_staging_external_runtime.shandtests/e2e/test_staging_full_saas.shchanged. Each addedset +eregion is immediately followed byset -e; no lingering disabled errexit. No workflow or continue-on-error changes. Required contexts are green: CI / all-required, E2E API Smoke Test, and Handlers Postgres Integration.Security: surfaced HTTP bodies are passed through
sanitize_http_bodyon the new missing-id failure paths, preserving the existing credential-safe behavior.Performance: no production code or gate assertion change; only shell error-handling around existing E2E create calls.
Readability: comments clearly explain the curl
--fail-with-bodyplusset -einteraction and why the scoped guard is needed.