Skip to content

fix(cli): flush api output before exit - #52955

Closed
Shalin-Shah-2002 wants to merge 1 commit into
anomalyco:devfrom
Shalin-Shah-2002:api-stdout-flush
Closed

Shalin-Shah-2002 wants to merge 1 commit into
anomalyco:devfrom
Shalin-Shah-2002:api-stdout-flush

Conversation

@Shalin-Shah-2002

@Shalin-Shah-2002 Shalin-Shah-2002 commented Oct 3, 2026 •

Copy link
Copy Markdown

Issue for this PR

Fixes #52925

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

opencode api get wrote its output with process.stdout.write(...) and returned, then the CLI entrypoint called process.exit(). When stdout is a pipe, Bun writes asynchronously, so a large response was cut off mid-flush (always on a 4096 multiple, exit code 0). File redirects are synchronous, which is why they worked.

The handler now waits for the write callback via a small writeStdout() helper (same approach session list already uses). The helper ignores EPIPE, so | head still exits quietly. I tried flushing with an empty write in index.ts first; Bun calls that callback immediately, so it does nothing.

Other handlers (session export, auth export, stats) have the same pattern. I left them out to keep this PR scoped to the issue.

How did you verify your code works?

Bun 1.4.2, real CLI against a local server returning a 600,012-byte response, read through a slow pipe (4 KiB every 5 ms):

  • before: 131,072 bytes
  • after: 600,012 bytes, valid JSON (3/3 runs)

Added src/stdio.test.ts: a slow-reader pipeline asserts writeStdout delivers all 600,000 bytes across process.exit, with a control showing a plain process.stdout.write is truncated. bun test src/stdio.test.ts src/commands/handlers/api.test.ts passes, and lint passes.

bun run typecheck in packages/cli is clean. (An earlier run showed unrelated errors in packages/core; they came from stale dependencies in my checkout and are gone after bun install.)

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

🤖 Generated with Claude Code

https://claude.ai/code/session_01HfXsWoKF5h7tmdmyUEw1rD

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@r266-tech

Copy link
Copy Markdown
Contributor

Independently checked abe4fed299 with the real V2 CLI on macOS arm64 / Bun 1.4.2 and a local HTTP fixture. All 600,095 bytes (including the newline) arrived intact through file redirection, a fast pipe, and a reader consuming 4 KiB every 5 ms; each exited 0. The same fixture previously truncated on both pipe readers.

A 503 response also delivered the complete body through all three readers and retained exit 1 plus the HTTP diagnostic. Closing the helper's pipe after 4 KiB exited 0 without stderr. The five stdio / API-resolution tests pass. This is local synthetic validation; I have not checked Linux or Windows.

@Shalin-Shah-2002

Copy link
Copy Markdown
Author

Thanks for the independent verification, @r266-tech! I've rebased onto the latest v2 (no code changes). The logic is identical to abe4fed299.

@thdxr
thdxr changed the base branch from v2 to dev October 10, 2026 19:29
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

@matt8s

matt8s commented Nov 4, 2026 •

Copy link
Copy Markdown

This still addresses the API pipe-truncation reports in #60395 and #60231. Please consider reopening it rather than starting a duplicate implementation.

Linux/Bun 1.4.4 synthetic validation of this implementation in an integration branch delivered the complete JSON through a real OS pipe, with matching byte count and SHA-256. The unpatched writer truncated the same response despite exiting 0. This is scoped pipe validation, not a claim that the entire upstream suite passed.

One behavior is worth reconsidering: writeStdout resolves on EPIPE. That is convenient for | head, but lets incomplete structured output look successful to callers that inspect the writer's exit status. For API output used as an archive, rejecting the write error is safer:

if (error) return reject(error);
resolve();

The regression can avoid sleeps: spawn a writer blocked on stdin, close its stdout reader, then release stdin. Handle the stream's error event in the fixture so the assertion checks the helper's rejection rather than an incidental unhandled event. The writer should reject with EPIPE and exit nonzero. The existing complete-output pipe test should continue to pass.

A tested follow-up preserving this PR's original history is available at matt8s@99e7f1c. The two changed blobs match the successful Linux integration validation, including full Core/CLI tests and compiler checks. No separate duplicate implementation PR was opened.

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.

cli: "api get" truncates stdout when it is a pipe

3 participants