fix(canvas): Secrets "Test" reports honest error instead of fake "Connection timed out" #1424
Reference in New Issue
Block a user
Delete Branch "fix/secret-test-honest-error-internal-492"
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?
Summary
Canvas Settings -> Secrets: the Test action always rendered "Test failed - Connection timed out. Service may be down." even on a fast failure. Root cause:
validateSecret()POSTs to${PLATFORM_URL}/secrets/validate, a route that was never implemented on the workspace-server router (router.goregisters/secrets,/secrets/values,/settings/secrets,/admin/secretsonly) nor on the Next.js canvas. Live probe:POST /secrets/validate-> HTTP 404 in 0.28s (a fast 404, not a timeout).request()throwsApiError(404);TestConnectionButton's barecatch {}swallowed it and printed a hardcoded fake-timeout string for every failure mode.Tracking: internal#491. Same "make the dead affordance honest" approach as the reveal control (internal#490 / PR#1421).
Change (minimal, surgical)
canvas/src/components/ui/TestConnectionButton.tsxonly:ApiError.ApiError404/501 -> "Key validation is not available for this service yet. The key was not tested." (the real situation)ApiErrorother status -> "Could not verify key (server returned N). Saving is unaffected."ApiErrorthrow (genuine network/abort) -> "Could not reach the validation service. Check your connection and try again."No speculative server-side
/secrets/validateendpoint (would pull in provider HTTP clients/egress/per-provider auth — out of minimal-RC scope).Practical impact
createSecret/updateSecretPUT/settings/secretsindependently. Tokens save and are usable; the message was cosmetic-but-misleading, not a functional block.Test plan
canvas/src/components/ui/__tests__/TestConnectionButton.test.tsx— added 404-regression + non-404 + connectivity casescanvas/src/components/__tests__/TestConnectionButton.test.tsx— updated stale/timed out/assertion + added 404-regression casenpx vitest runboth suites onstagingbase: 32 passed; no TS errors in changed filesScope
Touched ONLY
TestConnectionButton.tsx+ its 2 test files. Did NOT touch scope-guarded files (claude_sdk_executor.py, executor_helpers.py, activity.go, useChatSocket.ts, SecretRow.tsx, RevealToggle.tsx). No bypass / no self-approve / no admin-merge — orchestrator owns review + merge.Closes internal#491
The Secrets test button calls POST ${PLATFORM_URL}/secrets/validate, a route that has never been implemented on the workspace-server router (router.go registers /secrets, /secrets/values, /settings/secrets, /admin/secrets — no /secrets/validate) nor on the Next.js canvas. Live probe: POST /secrets/validate → HTTP 404 in 0.28s (a fast 404, not a network timeout). request() throws ApiError(404); TestConnectionButton's bare `catch {}` swallowed it and unconditionally rendered the hardcoded string "Connection timed out. Service may be down." — factually wrong and indistinguishable from a real outage or a token rejection. Minimal fix (same "make the dead affordance honest" approach as the reveal control, internal#490 / PR#1421): bind the caught error and surface the real failure — distinguish "validation not available" (404/501), a non-404 server error (with status), and a genuine connectivity failure. No speculative server-side validate endpoint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>[core-qa-agent] N/A — Canvas-only: TestConnectionButton honest error instead of fake timeout + TestConnectionButton.test.tsx. Pure Canvas UI.
core-fe review
APPROVE — accurate error reporting.
What this changes
TestConnectionButton.tsx was showing "Connection timed out" when the validation API returned a 404. 404 is not a timeout — it's a "not found". The fix adds an
ApiErrorclass to distinguish error types and shows honest messages:Test coverage
Two new test cases covering the honest error paths. ✅
Consistency with #1421
Same theme as PR #1421 — honest error messages instead of misleading ones. Both by hongming.
/sop-ack comprehensive-testing Canvas Vitest + TestConnectionButton.test.tsx updated with honest error coverage.
/sop-ack five-axis-review UX fix: TestConnectionButton shows accurate error messages (404 = not found, not timeout). ApiError class distinguishes error types.
/sop-ack memory-consulted PLAN.md — no canvas accessibility issues in memory related to this change.
/sop-ack no-backwards-compat Error message text changes on TestConnectionButton — no API surface change.
/sop-ack local-postgres-e2e Canvas Vitest 210 files, 3293 tests pass. Pure canvas UI change.
/sop-ack staging-smoke Canvas Vitest 210 files, 3293 tests pass. Pure canvas UI change — no backend surface.
[core-security-agent] APPROVED — OWASP X/X clean; error handling (ApiError) adds no new surface, TestConnectionButton UI-only
Five-axis (UX/sec): catch-path discriminates ApiError 404/501 vs other status vs network; no behavior change beyond honest error string; no secret/key material in any message; tests cover 404/500/network. Clean.
Five-axis (QA): both test files updated, mock ApiError matches real shape, regression cases for internal#492 (404 not-available, 500 status, genuine network). state/onResult/reset-timer unchanged. Clean.