fix(cli): distinguish an unenrolled project from a missing one on the compute routes - #6645
Conversation
Both compute-api.ts and compute-logs-api.ts repeated the same read-body-as-text-or-empty and json-then-decode sequences; pull them into bodyText and decodeJsonBody so the upcoming 404 classification work has one place to read a response's body from.
The Management API answers 404 with the same not_found code for three unrelated conditions: no such project, no such route, and (on the named-compute routes) an undeployed compute. Callers read all of these as either "missing project" or "not deployed", so a route the CLI's own version has fallen behind on was misreported as "no project ref was found", sending someone to re-link a project that was never the problem. Add ComputeRouteNotFoundError and recognize the router's own "Cannot GET /..." body so a 404 from an unserved route is named for what it is, on both the collection endpoints and the named-compute get/delete routes.
`status` and `delete` read every 404 the compute route answered as "not deployed", so a project outside the alpha was told its compute was missing. Branch on the `not_found.compute.not_enabled` code the API now carries, on both route families, and point at the public alpha rather than at enrolment.
There was a problem hiding this comment.
🤖 AI Review
The named-compute 404 handling has a major confirmed bug: missing projects are still treated as undeployed computes or successful deletes. Most other confirmed findings are stale documentation, overly broad retry/classification behavior, and outdated test fixtures. One proposed router-body robustness issue remains uncertain because the checked-in code documents and tests only the structured envelope.
Findings
| Severity | Location | Category | Sources | Claim |
|---|---|---|---|---|
| 🟠 MAJOR | apps/cli/src/shared/compute/compute-api.ts:182 |
error-handling |
codex | Named GET and DELETE requests treat a nonexistent project as an absent compute or successful deletion instead of raising ComputeProjectNotFoundError. |
| 🟡 MINOR | apps/cli/src/shared/compute/compute-api.ts:339 |
documentation |
claude | The deleteCompute comment incorrectly describes every 404 as an already-completed delete even though two classified 404 bodies now fail. |
| 🟡 MINOR | apps/cli/src/shared/compute/compute-api.ts:112 |
error-handling |
claude | Router-404 recognition fails when the router message is not accompanied by the expected error envelope and code, causing fallback misclassification. |
| 🟡 MINOR | apps/cli/src/shared/compute/compute-api.ts:388 |
error-handling |
claude | awaitComputeBuild retries the newly introduced permanent route-not-found and unavailable failures for up to 30 seconds before surfacing them. |
| 🟡 MINOR | apps/cli/src/shared/compute/compute.errors.ts:208 |
documentation |
claude | ComputeUnavailableError's comment incorrectly says the error is raised only on collection endpoints, although named GET and DELETE routes now raise it too. |
| 🟡 MINOR | apps/cli/src/commands/experimental/compute/delete/SIDE_EFFECTS.md:59 |
documentation |
claude | The delete exit-code contract incorrectly says every DELETE 404 succeeds, although router and not-enrolled 404 responses now fail. |
| 🟡 MINOR | apps/cli/src/commands/experimental/compute/delete/delete.handler.ts:70 |
documentation |
claude | The preflight GET is described broadly as a courtesy rather than a prerequisite, but an unrouted GET aborts deletion before DELETE is attempted. |
| ⚪ NIT | apps/cli/src/shared/compute/compute-logs-api.ts:159 |
consistency |
claude | fetchComputeLogs maps every 404 to ComputeUnavailableError, including 404s caused by a missing project or unserved logs route. |
| ⚪ NIT | apps/cli/src/commands/experimental/compute/push/push.integration.test.ts:1035 |
test-coverage |
claude | The push enrollment test still uses generic_not_found, so it exercises only the unrecognized-body fallback rather than the new not-enrolled code. |
| ⚪ NIT | apps/cli/src/commands/experimental/compute/list/list.integration.test.ts:341 |
test-coverage |
codex | The older list enrollment test still uses generic_not_found and now redundantly exercises the fallback instead of the explicit enrollment-code branch. |
Findings outside the diff
- 🟡 MINOR
apps/cli/src/shared/compute/compute.errors.ts:208— ComputeUnavailableError's comment incorrectly says the error is raised only on collection endpoints, although named GET and DELETE routes now raise it too. - 🟡 MINOR
apps/cli/src/commands/experimental/compute/delete/SIDE_EFFECTS.md:59— The delete exit-code contract incorrectly says every DELETE 404 succeeds, although router and not-enrolled 404 responses now fail. - 🟡 MINOR
apps/cli/src/commands/experimental/compute/delete/delete.handler.ts:70— The preflight GET is described broadly as a courtesy rather than a prerequisite, but an unrouted GET aborts deletion before DELETE is attempted. - ⚪ NIT
apps/cli/src/commands/experimental/compute/push/push.integration.test.ts:1035— The push enrollment test still uses generic_not_found, so it exercises only the unrecognized-body fallback rather than the new not-enrolled code. - ⚪ NIT
apps/cli/src/commands/experimental/compute/list/list.integration.test.ts:341— The older list enrollment test still uses generic_not_found and now redundantly exercises the fallback instead of the explicit enrollment-code branch.
Stats
Claude findings: 8 · Codex findings: 1 · Confirmed: 9 · Refuted: 0 · Uncertain: 1
Models: claude-opus-5 + gpt-5.6-sol · Trigger: auto · Workflow run
This review runs once per PR. A maintainer can request another with a /ai-review comment.
…med routes
`not_found.compute.instance` is the code an absent compute answers with, so a
plain `not_found` on `GET`/`DELETE /compute/{name}` is a missing project and
now reports as one instead of "not deployed" or a delete that happened.
The poll behind `push` stops retrying the verdicts a retry cannot change, the
logs 404 classifies its own body rather than blaming the alpha for every one,
and the 404 body reader moves next to the other shared response helpers.
|
Review findings addressed in 7fc9f66. The five that landed outside the diff:
Also confirmed from |
Depends on https://github.com/supabase/platform/pull/38464
The Management API answers 404 on the compute routes for several distinct conditions, and the CLI was collapsing them into the wrong message:
No project <ref> was found for this accounton the collection routes, and"<name>" is not deployedonstatusanddelete— sending someone to re-link or re-push a project that was never the problem."<name>" is not deployedonstatus, anddeletereported removing it.Each condition carries its own
error.code, so each now gets its own error, on every route including the named-computestatusanddeleteones:not_found.compute.not_enabledComputeUnavailableError, pointing at the public alpha rather than asking the reader to seek enrolmentnot_found, with the router'sCannot GET /…messageComputeRouteNotFoundError, naming the routenot_foundComputeProjectNotFoundError, which now means only what it saysnot_found.compute.instanceComputeNotDeployedError, the only one the named routes can meanThe poll behind
pushno longer retries the three permanent verdicts for its full 30-second window, and the analytics logs route — which is not gated on the alpha's allow-list — classifies its own 404 body instead of blaming the alpha for every one.Also extracts
bodyText,unexpectedStatus(operation, response),decodeJsonBodyand the 404 body reader incompute-api-status.tssocompute-api.tsandcompute-logs-api.tsshare one place to read a response body, instead of threading status and body through every call site.The enrolment split depends on the Management API emitting
not_found.compute.not_enabled, which is not deployed yet. Until it is, an unenrolled project answers a baregeneric_not_found, which no branch claims and which falls back to the alpha refusal — so the enrolment message is already right, and only its precision waits on the API. FUNC-897 should stay open until the API side is live.https://linear.app/supabase/issue/FUNC-897/fix-no-project-ref-was-found-for-unenrolled-compute-projects