Skip to content

chat: pasting external PDF path triggers HTTP 500 instead of graceful fallback for models without PDF support #55387

Closed as duplicate

Description

@IceofTea

Summary

When the active model does not support PDF input, pasting an absolute path to a PDF outside the workspace into the prompt composer renders a PDF 1 attachment chip, and sending then fails with Failed to send prompt / UnexpectedStatus: 500. PDFs inside the workspace degrade gracefully instead (the model receives a readable "does not support pdf input" error and the agent can fall back to local tooling), so only the outside-workspace case hard-fails and the request never reaches the agent.

Environment

  • opencode version: 2.0.28
  • OS: Windows_NT 10.0.26100 (win32 x64)
  • Terminal: Unavailable: terminal environment variables are not set
  • Shell: C:\WINDOWS\system32\cmd.exe
  • Install/channel: release (latest)
  • Active plugins: None found in config

Reproduction

  1. Use a model without PDF/multimodal input support (e.g. a text-only free-tier model).
  2. In the TUI, paste an absolute path to a PDF located outside the current workspace (e.g. C:\Users\<user>\Downloads\paper.pdf). The composer detects it and shows a PDF 1 chip.
  3. Send the message.

Expected Behavior

Either: (a) graceful degradation like the in-workspace case — the model receives "Cannot read ... (model does not support pdf input)" and can process the file with local tools (e.g. a pdf skill); or (b) the client refuses the attachment with a clear user-facing message. In no case should sending hard-fail.

Actual Behavior

Failed to send prompt / UnexpectedStatus: 500 on every send. The request never reaches the model, so the agent's local-PDF fallback cannot run.

Additional Context

  • The same PDF referenced from inside the workspace works fine: model read fails → error text is delivered → the agent processes the file via local pdf tooling. Only the outside-workspace path (serialized into the request as a real attachment) hard-fails.
  • Workaround: paste the path without the .pdf suffix, or with surrounding text, so it is not parsed as an attachment; the agent then reads the file with local tools successfully.
  • Reproducible consistently.

Activity

  1. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report. I reproduced this on 2.0.28 and it still happens on the latest dev (34d8ded). It turns out to depend on the file size rather than on the file being outside the workspace or the model lacking PDF support.

    What I ran: in the TUI with a simulated model, I pasted the absolute path of a PDF from a folder outside the project, so the PDF 1 chip appeared, then sent a message.

    • With a tiny PDF (193 bytes), the message went through and the model replied.
    • With a ~7 MB PDF, sending failed with Failed to set up session / UnexpectedStatus: 500 and the prompt never reached the model.

    The server validates each attachment's base64 data with a regular expression that wrongly rejects valid data once the attachment is larger than about 6 MB. The request then fails with a 500 before the model is involved. That's why paths that aren't turned into an attachment, like your workaround, still work.

    This looks like the same root cause as #45558 (which has a proposed fix in #51272), and #54323 was already closed as a duplicate of it. If your PDF is smaller than ~6 MB, please say so here, because that would point to a separate problem.

    The recording and script below show both cases.

    recording.mp4

    Screenshot

    Screenshot

    Reproduction script (drive.ts)
    // Repro for anomalyco/opencode#55387: pasting the path of a PDF outside the
    // workspace into the TUI composer attaches it; sending fails with HTTP 500.
    // Creates /tmp/outside/small.pdf (193 B) and /tmp/outside/big.pdf (~7 MB) first.
    import { Effect, Stream } from "effect"
    import { mkdirSync, writeFileSync } from "node:fs"
    import { randomBytes } from "node:crypto"
    import { Llm, OpenCodeDriver } from "opencode-drive"
    
    const which = process.env.PDF ?? "big"
    const pdf = Buffer.from(
      "%PDF-1.4\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj\n3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 200 200]>>endobj\ntrailer<</Root 1 0 R>>\n%%EOF\n",
    )
    mkdirSync("/tmp/outside", { recursive: true })
    writeFileSync("/tmp/outside/small.pdf", pdf)
    writeFileSync("/tmp/outside/big.pdf", Buffer.concat([pdf, randomBytes(7 * 1024 * 1024)]))
    const path = `/tmp/outside/${which}.pdf`
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        project: { git: true, files: { "README.md": "hello\n" } },
        tui: { recording: true, keypressOverlay: true },
      },
      ({ ui, llm }) =>
        Effect.gen(function* () {
          yield* llm.serve(() => Stream.make(Llm.text("I received your message.")))
          yield* Effect.sleep(1500)
          // Bracketed paste of the absolute path, as a terminal paste would deliver it
          yield* ui.type(`\x1b[200~${path}\x1b[201~`)
          yield* Effect.sleep(1500)
          yield* ui.screenshot(`${which}-pasted`)
          yield* ui.type(" summarize this pdf")
          yield* ui.enter()
          yield* Effect.sleep(5000)
          yield* ui.screenshot(`${which}-after-send`)
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

  2. IceofTea commented on Oct 14, 2026

    @IceofTea
    Author

    Thanks for the detailed triage! My PDF was 15.3 MB (16,086,359 bytes) — well above the ~6 MB threshold, so this matches the #45558 root cause and is not a separate sub-6MB issue. Feel free to close as a duplicate of #45558 if appropriate.

  3. Tarquinen commented on Oct 20, 2026

    @Tarquinen
    Member

    Thanks for the report! As you mentioned, this is a duplicate of #45558, so I'm closing it. Please follow that issue for updates.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions