Skip to content

fix(cli): name the changed setting and the fix when a saved stack rejects a config change - #6944

Merged
jgoux merged 6 commits into
developfrom
juliengoux/cli-2588-name-the-changed-setting-and-the-fix-when-a-saved-stack
Oct 2, 2026
Merged

jgoux merged 6 commits into
developfrom
juliengoux/cli-2588-name-the-changed-setting-and-the-fix-when-a-saved-stack

Conversation

@jgoux

@jgoux jgoux commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

When supabase start (with [experimental] stack) refuses a change to a saved stack, the error now says which setting changed and what to do about it. It used to report internal paths such as endpoints.http with a generic suggestion.

  • Each rejected change is reported as the config.toml key, or the SUPABASE_* environment variable that set it, with the saved and requested values, after a lead-in saying the saved stack cannot adopt them. For example: [db] major_version: saved 17, requested 15, or [api] port: saved automatic, requested 54999.
  • Changes across all affected services are reported together in one error. A shared [api] port appears once.
  • The suggestion offers two ways out: revert the setting to keep the stack and its data, or run supabase stack destroy --stack-id <id> to recreate it. It warns that recreating deletes the local database data. The ID is used so the command targets this stack regardless of the current directory. When a change can't be reverted, such as a catalog-pinned artifact or Postgres build from a CLI upgrade, the suggestion offers only the destroy command.
  • JSON and stream-json errors carry the same details in structured form (stack_changes with service, path, key, saved and requested values, plus recreate_command), so agents don't have to parse prose. stack_changes keeps one entry per affected service, and recreate_command omits --yes, which a JSON-mode destroy requires.

Port settings are now defined once in stack-config.ts, shared by config translation and error attribution, so a new port can't be added to one and missed in the other. The tests use the real composition planner.

jgoux added 2 commits October 1, 2026 10:17
…ects a config change

Maps each incompatible plan path (endpoint port, db major version) to the
config.toml key or SUPABASE_*_PORT env var that set it, shows the saved and
requested values, and suggests reverting it or running the stack's exact
destroy command with a data-loss warning.
…mplete

Always suggest the exact --stack-id destroy command instead of an unquoted
--stack <name> that re-resolves against the caller's current workdir, carry
structured per-change records (service, path, key, saved, requested) plus
the recreate command on the JSON/stream-json error envelope via
MachineErrorContext, and collect every incompatible member into one error
instead of reporting only the first, deduplicating shared API port lines.

Use the production planSupabaseComposition planner in the start handler's
integration tests instead of a hand-rolled approximation, and derive the
port-setting table and createCreations' env-override calls from one shared
definition per port to prevent drift.
@jgoux
jgoux requested a review from a team as a code owner October 1, 2026 13:02
@jgoux jgoux self-assigned this Oct 1, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Review

Verified all 10 supplied findings against the checked-out code and trusted conventions. Three overlapping pairs merge into seven confirmed findings: two minor error-guidance issues and five nits. Full PostgreSQL pins can produce identical displayed major versions despite an incompatibility, and artifact-version mismatches receive advice to revert a setting the CLI does not expose. No critical or major issue was established. Locations below use the actual new-side line numbers.

Findings

Severity Location Category Sources Claim
🟡 MINOR apps/cli/src/commands/experimental/stack/start/start.handler.ts:229 error-messages claude When saved and requested PostgreSQL pins differ within the same major version, the error displays identical major versions and suggests reverting a major_version setting that already matches.
🟡 MINOR apps/cli/src/commands/experimental/stack/start/start.handler.ts:328 error-handling claude+codex Artifact-version mismatches receive instructions to revert a setting that has no config.toml key or environment override in the CLI.
⚪ NIT apps/cli/src/commands/experimental/stack/start/start.handler.ts:328 wording claude+codex Multiple changed settings produce the grammatically incorrect suggestion 'Revert the settings above to its saved value', although the changes are joined inline.
⚪ NIT apps/cli/src/command-internal/stack-config.ts:173 documentation claude+codex The PortSetting comment promises automatic consistency between creation wiring and endpoint-setting lookup that the implementation does not enforce.
⚪ NIT packages/stack/src/effect.ts:71 api-surface claude The PR adds a planner re-export to the main Effect entrypoint for a new consumer that exists only in a CLI integration-test fake.
⚪ NIT apps/cli/src/commands/experimental/stack/start/start.handler.ts:299 code-quality claude destroyCommandFor accepts an unused name property, and the same rejection constructs the destroy command separately for prose and structured output.
⚪ NIT apps/cli/src/commands/experimental/stack/start/start.handler.ts:177 comment-style codex The new internal-helper comments narrate implementation mechanics prohibited by the trusted repository comment policy.

Stats

Claude findings: 6 · Codex findings: 4 · Confirmed: 7 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts Outdated
Comment thread apps/cli/src/command-internal/stack-config.ts Outdated
Comment thread packages/stack/src/effect.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts Outdated
jgoux added 3 commits October 1, 2026 15:18
…name-the-changed-setting-and-the-fix-when-a-saved-stack
…in the stack error

Same-major Postgres version differences and catalog-pinned artifact versions have
no config.toml key or env var, so the incompatible-stack error no longer suggests
reverting major_version or an editable setting for them: it names the full saved
and requested builds, drops the revert sentence when nothing is editable, and
explains the fix in plain language. Mixed rejections keep the revert advice for
the editable keys only, with singular/plural grammar matching their count.

destroyCommandFor now takes only the stack id (it never read the name) and is
computed once per rejection, reused for both the error suggestion and the
JSON/stream-json envelope's recreate_command.

Move planSupabaseComposition's export from the main @supabase/stack/effect
entrypoint to @supabase/stack/testing, since the CLI only needs it to build a
realistic test double for its own composition plan.

@avallete avallete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dogfooded from source on 0247b903b (Docker and native runtimes, usebasejump__basejump sample) and reviewed. Nice improvement — the messages read well and the structured envelope works. One correctness issue in the advice text is worth fixing before merge; the rest is non-blocking.

Dogfood results

Scenario Result
[db] port changed in config.toml ✅ [db] port: saved A, requested B, singular revert advice, --stack-id matches stack status
SUPABASE_DB_PORT from shell env and from supabase/.env ✅ both labelled SUPABASE_DB_PORT
[api] port changed (5 services share it) ✅ exactly one [api] port line
automatic → fixed [api] port ✅ saved automatic, requested N
[db] major_version 17 → 15, via toml and SUPABASE_DB_MAJOR_VERSION ✅ saved 17, requested 15, env label when env-driven
db + api + studio ports changed together ✅ one error, plural advice
--output-format json / stream-json ✅ stack_changes + recreate_command present, non-zero exit
Named stack (--stack dogfood-a) ✅ (stack dogfood-a) in the suggestion
Revert the setting → start ✅ same stack id, data preserved (rejected attempt did not modify the stack)
Run recreate_command verbatim from another cwd ✅ destroys the right stack; next start succeeds
Unchanged restart / only --exclude set changed ✅ no false rejection
Native runtime ([db] port change) ✅ same message shape
Top-level supabase start with stack = true ✅ same handler and message
Fixed → automatic [api] port (key removed) ℹ️ start succeeds and keeps the saved port (planner sticky-port behaviour, locked by the "accepts a shared API port going from fixed back to automatic" test). The PR description's [api] port: saved 54321, requested automatic example doesn't occur for this direction — worth updating the example.

Not reachable without a catalog change, so not dogfooded: same-major Postgres build mismatch, artifact-version mismatch. Integration file passes locally (39/39); types:check clean in apps/cli and packages/stack.

Review

  • Should fix: mixed editable + non-editable rejection advises a revert that cannot unblock start (inline).
  • Non-blocking: text message has no headline; several test assertions are guarded by instanceof and can pass vacuously; one duplicated test; stack_changes vs text dedupe contract (inline).
  • Minor nit: recreate_command omits --yes, and stack destroy in JSON mode requires it, so an agent running it verbatim hits the confirmation error. Leaving --yes out is the safer default for a data-deleting command; maybe just mention it in the suggestion or docs.

Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts
Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/start/start.handler.ts
Comment thread apps/cli/src/commands/experimental/stack/start/start.integration.test.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/start/start.integration.test.ts Outdated
…tart

A rejected config change that mixed an editable key (e.g. a port) with a
non-editable one (a catalog-pinned artifact or Postgres build) suggested
reverting the editable key and dropped the non-editable change, but
reverting it alone can't unblock start. Use the destroy-only wording
whenever any non-editable change is present, and lead the change-list
message with a sentence so it reads standalone in text output.

Also document the `stack_changes`/`recreate_command` JSON contract and the
intentional `--yes` omission, and make several integration-test assertions
that lived inside `if (error instanceof StackCommandStartError)` fail
loudly instead of passing vacuously for a different error type.
@jgoux

jgoux commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough dogfooding. Addressed in cdaef16; the inline threads have the details. On the summary notes:

  • The description's example now uses [api] port: saved automatic, requested 54999, since fixed → automatic keeps the saved port and isn't rejected.
  • recreate_command still omits --yes, as the safer default for a data-deleting command. SIDE_EFFECTS.md and the PR description now say so, including that a --output-format json/stream-json destroy needs --yes explicitly.

@jgoux
jgoux added this pull request to the merge queue Oct 2, 2026
Merged via the queue into develop with commit 2d92610 Oct 2, 2026
68 of 69 checks passed
@jgoux
jgoux deleted the juliengoux/cli-2588-name-the-changed-setting-and-the-fix-when-a-saved-stack branch October 2, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants