Skip to content

fix(client): surface managed startup stderr - #41793

Merged
kitlangton merged 6 commits into
v2from
startup-stderr
Aug 12, 2026
Merged

fix(client): surface managed startup stderr#41793
kitlangton merged 6 commits into
v2from
startup-stderr

Conversation

@kitlangton

Copy link
Copy Markdown
Contributor

What

Surface actionable stderr when a managed background-service contender exits unsuccessfully. This lets opencode2 service start report the existing port-conflict guidance instead of reducing it to an exit code.

Closes #41696

Before / After

Before: serve --service emitted the actionable port-conflict diagnostic, but Service.ensure spawned it with stdio: "ignore". The managed client saw only Server process exited with code 1 and could continue spawning contenders without exposing the cause.

After: managed contenders continuously retain only the final 8 KiB of stderr. Once a contender closes with a nonzero exit or signal, its startup error includes that tail, so the configured-port remediation reaches the caller.

How

  • packages/client/src/effect/service.ts captures a bounded stderr tail and waits for child close so output is drained before formatting failures.
  • packages/client/src/promise/service.ts mirrors the same behavior without adding an Effect runtime dependency.
  • The stderr pipe and child remain unrefed so a successful detached service does not keep the client alive.
  • Client fixtures verify tail bounding for both APIs; the CLI regression exercises a real child process through the managed Service.ensure boundary using the same actionable conflict text.

Scope

Testing

  • cd packages/client && bun run test test/service.test.ts test/promise-service.test.ts (21 passed)
  • cd packages/cli && bun run test test/service.test.ts --test-name-pattern "managed service startup reports an actionable port conflict|unrelated managed port occupancy reports an actionable conflict" (2 passed)
  • cd packages/client && bun typecheck
  • cd packages/cli && bun typecheck
  • bunx prettier --check packages/client/src/effect/service.ts packages/client/src/promise/service.ts packages/client/test/service.test.ts packages/client/test/promise-service.test.ts packages/client/test/fixture/service.ts packages/cli/test/service.test.ts
  • Push hook: bun turbo typecheck --concurrency=3 (33 tasks passed)

Flow

sequenceDiagram
    participant Client as Service.ensure
    participant Child as serve --service contender
    Client->>Child: spawn detached with stderr pipe
    Child-->>Client: stderr chunks
    Client->>Client: retain final 8 KiB
    Child-->>Client: close with nonzero exit
    Client-->>Client: append stderr tail to startup error
Loading

@kitlangton
kitlangton marked this pull request as ready for review August 12, 2026 00:39
# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
#
# Conflicts:
#	packages/client/src/effect/service.ts
#	packages/client/src/promise/service.ts
@kitlangton
kitlangton merged commit 9322f5d into v2 Aug 12, 2026
8 checks passed
@kitlangton
kitlangton deleted the startup-stderr branch August 12, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant