[BUG] /export produces 0-byte files and empty clipboard — rendering pipeline returns empty string

Status Fixed / completed
Reported on v2.1.98
Maintainer reply ✓ Yes — ashwin-ant
Activity 13 comments · opened Apr 10, 2026 · closed Apr 19, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

/export consistently produces empty output. Both the file and clipboard paths generate 0 bytes of content. The command appears to succeed — the "Conversation exported to: ..." message is displayed — but the resulting file is 0 bytes. Clipboard export similarly reports success while the clipboard is empty. This occurs regardless of conversation length, including long sessions with hundreds of messages.

What Should Happen?

/export test-output should produce a non-empty file containing the conversation transcript. /export → "Copy to clipboard" should place the conversation text on the system clipboard.

Error Messages/Logs

No error is displayed. The success message shows normally:
  "Conversation exported to: test-output.txt"
But:
  $ ls -la test-output.txt
  -rw-r--r--  1 user  staff  0 Apr  9 19:30 test-output.txt

Steps to Reproduce

  1. Start a Claude Code session (CLI, Homebrew cask binary)
  2. Have any conversation (even a single exchange works)
  3. Run /export test-output
  4. Check file size: ls -la test-output.txt → 0 bytes
  5. Or: run /export, select "Copy to clipboard", paste → empty

Claude Model

Opus

Is this a regression?

Yes; /export worked in previous versions.

Claude Code Version

2.1.98 (Claude Code)

Platform

Anthropic API

Operating System

Multiple: macOS, also confirmed on Fedora Linux by @Cianidos

Terminal/Shell

iTerm2

Additional Information

I traced through the minified source in the npm package (cli.js from @anthropic-ai/claude-code@2.1.98). The rendering pipeline for /export is:

/export → agY() → ogY() → zi8() → igY() → c58()

Root cause: c58 (render-to-string) returns empty, and igY has no recovery path.

c58 renders the transcript via Ink to a PassThrough stream. It captures only the first data event:

async function c58(q, K) {
    let _ = "", z = false, Y = new PassThrough();
    if (K !== undefined) Y.columns = K;
    return Y.on("data", (O) => {
        if (z) return;
        z = true;
        _ = O.toString();
    }),
    await (await XB(createElement(FkY, null, q), 
           { stdout: Y, patchConsole: false })).waitUntilExit(),
    _;
}

The PassThrough has no columns/rows/isTTY properties (the Ink renderer defaults to 80×24, so dimensions aren't the direct cause). The FkY wrapper exits via setTimeout(exit, 0) after one render frame.

Then igY breaks on the first empty chunk with no fallback:

for (let j = 0; j < $; j += A) {
    let H = await w([j, j + A]);
    if (MO(H).trim() === "") break;  // all-or-nothing exit
    await _(H);
}

MO is stripAnsi. If the rendered frame is whitespace/ANSI-only, trim() yields "" and the entire loop exits immediately — zero content is collected.

Both export paths then silently write the empty string:

  • File: _i8(filename, "") → 0-byte file + success message
  • Clipboard: WP("")pbcopy with empty stdin + success message

Three possible triggers (couldn't narrow further without debugger access):

A. Stream timing — The Homebrew cask binary runs on Bun (Bun.FFI / Bun.stripANSI confirmed in binary strings). Bun's PassThrough may not synchronously emit the data event on .write(). If it fires after waitUntilExit() resolves, _ stays "".

B. Empty screen renderrenderFullFrame (the non-TTY path, since PassThrough.isTTY is undefined) iterates screen cells. If Yoga layout produces zero-height content, the output is only newlines → stripAnsi().trim()"".

C. Render contextc58 creates a fresh Ink instance with a bare AppStateProvider (no initialState). If the transcript component reads any state from context rather than its direct props, it sees an empty default state.

Suggested fixes:

  1. Collect all data chunks instead of only the first event
  2. Use continue instead of break in igY, or remove the early exit
  3. Report empty export as a failure — don't show a success message for 0-byte output

View original on GitHub ↗

13 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/38667
  2. https://github.com/anthropics/claude-code/issues/38805
  3. https://github.com/anthropics/claude-code/issues/41923

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

ylluminarious · 4 months ago

Note: this is still occurring as of Claude Code 2.1.100

ylluminarious · 4 months ago

Still broken as of Claude Code 2.1.101

NathanSmeltzer · 4 months ago

Still broken on v2.1.104

ylluminarious · 4 months ago

Still broken on 2.1.105...

Cianidos · 4 months ago

Claude Code v2.1.107 still broken, on Fedora Linux

solrevdev · 4 months ago

Still broken on Claude Code v2.1.109 on macOS

hunmix · 4 months ago

Still broken on v2.1.110

ylluminarious · 4 months ago

Still broken on 2.1.112... not sure why a whole week isn't enough to fix this bug even after I provided concrete suggestions for how to do so in my initial submission...

ylluminarious · 4 months ago

Confirmed that 2.1.114 is also still broken.

paulmvpbuild · 4 months ago

I also had this error, 0 byte exports. One workaround I found was to point Claude at its own error, which it then acknowledged after I deleted the empty files, and then asked it to do the export manually which gave me the correct files.

  1. /export "export.txt"
  2. When I use "/export" the output is zero bytes
  3. Can you do the export? Export the transcript to export1.txt and export2.txt etc if there is more than 1

It reported that the raw session transcript is live at: project dir/BLAHBLAH.jsonl 15MB, JSONL, one message per line. You can grep it, or pipe through jq to extract text: jq -r 'select(.message.content) | .message.content' BLAHBLAH.jsonl > session.md

ashwin-ant collaborator · 4 months ago

This has been fixed in a recent release — /export no longer produces 0-byte files. The fix will land in v2.1.115+. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.

github-actions[bot] · 4 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.