Repository navigation
Description
Summary
Attaching a file larger than about 3.2 MB to a prompt makes POST /api/session/:id/prompt fail with HTTP 500. The failure happens while materializing the attachment: the Prompt.Base64 schema uses a backtracking-prone regex that overflows the call stack on large strings (RangeError: Maximum call stack size exceeded), which is surfaced as a schema InvalidValue instead of a clear size/format error. Attachments well under the documented 20 MiB limit are affected.
Environment
- opencode version: 2.1.0 (server and TUI); desktop app 2.0.32 connects to the same local service
- OS: macOS (Darwin 25.6.0, arm64)
- Terminal:
xterm-256color,COLORTERM=truecolor - Shell:
/bin/zsh - Install/channel: npm global (
@opencode/cli) - Active plugins: none found
Reproduction
- Take any file larger than ~3.2 MB (a 5.7 MB PDF in my case).
- Attach it to a prompt (paste the absolute path or drag it in), so the client sends a
PromptInput.FileAttachment:{ "uri": "file:///Users/me/Desktop/large.pdf", "name": "large.pdf" } - Send the prompt.
Minimal reproduction of the underlying validator (same regex as Prompt.Base64, runs on the bundled Bun 1.4.2 and on Node):
const r = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
r.test("A".repeat(4_400_000)); // true
r.test("A".repeat(4_500_000)); // RangeError: Maximum call stack size exceededMeasured threshold on this machine: 4,473,912 base64 characters pass, 4,473,916 throw (about 3.2 MB of decoded data).
Expected Behavior
- Accept the attachment (it is under the documented 20 MiB limit), or
- Reject it with a 4xx and an explicit message (for example "attachment too large" or "unsupported attachment type"), never a 500.
Actual Behavior
POST /api/session/<id>/prompt returns HTTP 500 and the prompt is never sent to the model. Server log:
POST /api/session/<id>/prompt http.status=500
cause="Error: Schema validation failed
at SessionPrompt.normalizeImageAttachment
... Prompt.Base64 ... {"issue":{"_tag":"InvalidValue"}}"
Observed 7 times in a row, every attempt with the same 5.7 MB PDF.
Additional Context
-
SessionPrompt.normalizeImageAttachmentreturns{ data: Prompt.Base64.make(base64) }for every non-image mime type, so a PDF (detected via the%PDF-magic bytes) always goes through this regex. -
Base64 produced by
Buffer.from(bytes).toString("base64")is always structurally valid, so the schema failure can only come from the regex itself failing on large input. -
Per the V2 attachments docs, PDF and other unsupported binaries are not included in the model request anyway. Materializing them to a multi-megabyte base64 string only to fail the shape check is wasted work; rejecting unsupported binaries before materialization (with the documented "convert to text or PNG first" guidance) would be cheaper and clearer.
-
Suggested validator without the nested quantifier:
const isBase64 = (s: string) => s.length % 4 === 0 && s.length > 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(s);
and/or catch
RangeErrorand map it to a typed error instead of letting it become a schemaInvalidValue. -
Workaround I use now: pass the file path in the prompt and let the agent read it with a tool instead of attaching it. Reading the same 5.7 MB PDF through a tool works fine, so this is specific to the attachment path.
Activity
opencode-agent commentedon Oct 22, 2026
Thanks for the clear report and the minimal regex reproduction. I think this is a duplicate of #45558.
It's the same failure: the
Prompt.Base64check inpackages/schema/src/prompt.tsuses the repeated-group regex you quoted, and it fails on valid base64 once the string is a few MB long. As a result, any attachment over roughly 3–6 MB (depending on the runtime) returns HTTP 500 fromPOST /api/session/:id/promptwithSchema validation failed ... InvalidValue, even though it's under the 20 MiB limit. The regex is unchanged on the currentdevbranch. PR #51272 proposes a replacement without backtracking, but it hasn't been merged yet.Possible duplicates and related issues, ordered from most to least likely:
Prompt.Base64500 on/promptwith attachments, root-caused to the same regexPrompt.Base64validation (closed as a duplicate of attachments: dragging file or pasting file path into input fails session setup (Prompt.Base64 500 on /prompt) #45558)normalizeImageAttachmenton 2.1.2 (closed as a duplicate of attachments: dragging file or pasting file path into input fails session setup (Prompt.Base64 500 on /prompt) #45558)Your suggestion to reject unsupported binaries like PDFs before encoding them is a good one. It would fit well as a comment on #45558 or #51272.
Until the fix lands, your workaround of passing the file path and letting the agent read it with a tool avoids the problem. Converting the PDF to text first also works.
The bot will close this issue as a duplicate of #45558 in 1 day unless you reply explaining how your problem is different. Subscribing to #45558 or #51272 will let you follow progress.
opencode-agent commentedon Oct 23, 2026
Closing this as a duplicate of #45558, since there hasn't been a reply saying how it's different. It's the same
Prompt.Base64regex failure, which gives HTTP 500 onPOST /api/session/:id/promptfor attachments over a few MB. Your 5.7 MB PDF on 2.1.0 is one example. Closing just keeps the discussion in one place; the bug is still open. The proposed fix, PR #51272, hasn't been merged yet, so please subscribe to #45558 or #51272 to follow progress. Your idea of rejecting unsupported binaries before encoding them would be a good comment there too. Until then, your workaround still works: pass the path and let the agent read the file with a tool. Thanks again for the clear reproduction.