Skip to content

Show mixed or multi-file diff tool output as text instead of a blank "Invalid or empty patch" block #102

Closed

Description

@iamnbutler

In Canary 0.0.11, a bash tool result that contains a multi-file git diff mixed with other output renders as "Invalid or empty patch" followed by several screens of blank space. There is no raw-text fallback, so the result can't be audited in the chat.

Observed

Channel image-paste-review, agent response at 11:33 AM. Expand the command group, then expand the bash call:

git rev-parse origin/main HEAD; git diff origin/main; gh issue view 91 --repo githubnext/ace2 | head -40

The expanded result shows only "Invalid or empty patch" followed by blank space. Nate confirmed this from both the native Accessibility text and a screenshot.

Cause

The shell didn't fail. The tool result saved in the channel's database is intact: isError: false, 4,105 characters, 110 lines. It contains two commit SHAs, a valid two-file diff (chat-composer.tsx and rich-text.tsx), and then the gh issue view output.

The renderer treats the entire result as a single-file patch (all paths are at origin/main = 1ab91be, canary 0.0.11):

  1. isPatch() in packages/ui/src/components/blocks/tool-layout.ts matches any result that contains diff --git/---, +++, and @@ lines anywhere, so the whole mixed output gets routed to diffBlock(data.result).
  2. parseDiff() in packages/ui/src/lib/highlighter.ts calls @pierre/diffs getSingularPatch. That function throws FileDiff: Provided patch must contain exactly 1 file diff for this result. parsePatchFiles sees 1 patch with 2 files. parseDiff catches the error and returns null.
  3. With parsed === null, diff() in packages/ui/src/components/blocks/diff.tsx still sizes the block from the raw line count: 110 × 20 px + 12 ≈ 2,212 px. Diff (packages/ui/src/components/diff/diff.tsx) then renders the "Invalid or empty patch" box at that height, which produces the blank space. The raw text is never shown.

I reproduced this against the saved result with the bundled @pierre/diffs 1.2.10. Each file's diff parses on its own. A related silent loss: if the output has a single-file diff plus surrounding text, getSingularPatch succeeds but renders only the hunk lines. In that case the SHAs and the gh output disappear without any error.

Expected

  • Tool results are always readable. If rich diff parsing fails, show the result as plain (diff-highlighted) text, the same way other results are shown.
  • Non-diff output around a diff (command output, SHAs, issue text) is never dropped. Either render diff segments richly and keep the surrounding text in order, or fall back to text for the whole result.
  • Multi-file diffs either render every file or fall back to text. A diff must never be treated as invalid just because it contains more than one file.
  • The block height matches the content that is actually rendered. A failed parse never reserves a large blank height.
  • The full raw output can still be audited even when a rich rendering is shown.

Related: #54 (tool results and full output in the channel), #99 (plain-language account with an auditable trail). Dogfooding core/QOL: #5.

Activity

  1. added a commit that references this issue on Oct 14, 2026
    8d99806
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions