Skip to content

fix(cli): prevent fork-bomb when supabase-go binary is not found#5282

Merged
avallete merged 3 commits into
developfrom
claude/investigate-cli-hang-DpZ8V
May 18, 2026
Merged

fix(cli): prevent fork-bomb when supabase-go binary is not found#5282
avallete merged 3 commits into
developfrom
claude/investigate-cli-hang-DpZ8V

Conversation

@avallete
Copy link
Copy Markdown
Member

Fixes CLI-1488: the Go proxy layer was silently falling back to "supabase" on PATH when the supabase-go binary could not be resolved. When the shim itself is on PATH and supabase-go is not co-located, this fallback resolves to the shim and causes a fork-bomb (silent multi-minute hang in CI followed by SIGTERM).

Changes

  • Binary resolution: resolveBinary() now returns a BinaryResolution discriminated union ({ found: string } | { notFound: string[] }) instead of a fallback string. The notFound variant tracks all attempted locations for user-facing diagnostics.

  • Error handling: When binary resolution fails, makeGoProxyLayer now prints a specific diagnostic message to stderr and exits with code 1 via ProcessControl.exit(), rather than attempting to spawn a non-existent binary.

  • User-facing diagnostics: New formatGoBinaryNotFoundError() function generates a helpful error message that:

    • Lists all locations the resolver checked
    • Provides platform-specific curl | tar install snippets (when CLI_VERSION is not the dev sentinel and the host architecture is supported)
    • Suggests npm installation and SUPABASE_GO_BINARY environment variable as alternatives
  • Test coverage: Added comprehensive unit tests for formatGoBinaryNotFoundError() covering:

    • Basic error message formatting with all attempted locations
    • Dev build behavior (no curl snippet when CLI_VERSION is "0.0.0-dev")
    • Platform-specific snippet generation (linux x64, darwin arm64, win32 → windows mapping)
    • Unsupported architecture handling (no snippet when release asset doesn't exist)
    • Integration test verifying the layer refuses to spawn and exits 1 when binary is not found

The fix ensures the CLI fails fast with actionable guidance instead of silently fork-bombing itself.

https://claude.ai/code/session_01Lb1v3o9Dabe6qjH565ki4k

claude added 3 commits May 18, 2026 17:06
LegacyGoProxy.resolveBinary() previously returned the literal string
"supabase" as a last-resort fallback when no co-located supabase-go
nor any @supabase/cli-<platform> npm package could be found. When a
user installs the v2.99.0 release tarball by moving only the
`supabase` shim onto PATH and leaving `supabase-go` behind, that
fallback resolves to the shim itself — every legacy command then
spawns the shim recursively (stdio inherited, parent-side SIGTERM
masked by holdSignals), producing the silent multi-minute CI hang
that ends in SIGKILL from the runner.

Replace the fallback with a structured BinaryResolution result and
print a specific diagnostic listing every location the resolver
checked, with concrete remediation steps, then exit non-zero before
spawning anything.

https://claude.ai/code/session_01Lb1v3o9Dabe6qjH565ki4k
The "Docs: ..." line on the not-found diagnostic pointed at a page
that doesn't explain the two-binary tarball layout, so it added no
context for the user actually stuck. Replace it with a concrete
`curl | tar` snippet that uses the CLI_VERSION baked in at build
time and the host platform/arch — the asset filename is fully
constructed so the user can paste it as-is. Skip the snippet on
Windows (different asset format) and on dev builds where
CLI_VERSION resolves to the "0.0.0-dev" sentinel.

https://claude.ai/code/session_01Lb1v3o9Dabe6qjH565ki4k
The release pipeline publishes `supabase_<version>_windows_<arch>.tar.gz`
for every Windows target (in addition to .zip), so the `curl | tar`
remediation snippet is just as valid on Windows as on linux/darwin.
Drop the platform skip and map Node's historical `win32` to the
release asset's `windows` slug.

Switch from `os.arch()` to `process.arch` (same value) so the host
mock in the unit tests can shape both axes via Object.defineProperty
— ESM module namespaces aren't spy-able, so the os module couldn't
be intercepted directly.

https://claude.ai/code/session_01Lb1v3o9Dabe6qjH565ki4k
@avallete avallete requested a review from a team as a code owner May 18, 2026 17:31
@avallete avallete merged commit 8b3a1c6 into develop May 18, 2026
11 checks passed
@avallete avallete deleted the claude/investigate-cli-hang-DpZ8V branch May 18, 2026 18:01
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.

3 participants