anomalyco / anomalyco/opencode
[Bug]: unsupported or oversized image attachment aborts the entire prompt (HTTP 400) in the user-message path
@neriousy is already working on this.
Since Aug 18, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
Attaching an image in a format the Photon-based resizer cannot decode (e.g. AVIF, HEIC, BMP, TIFF) — or an image too large to be resized below the inline limit — makes the entire prompt request fail with a 400 instead of degrading gracefully.
Expected Behavior
A single undecodable/oversized image attachment should not abort the whole message. It should be dropped (or replaced with a text note) while the rest of the prompt still sends — exactly like the tool-result path does today.
Current Behavior
packages/opencode/src/session/prompt.ts (user-message path, createUserMessage) runs image.normalize(part) inside a plain Effect.forEach that only catches Image.ResizerUnavailableError:
const parts = yield* Effect.forEach(resolvedParts, (part) =>
part.type === "file" && part.mime.startsWith("image/")
? image.normalize(part).pipe(
Effect.catchIf(
(error) => error instanceof Image.ResizerUnavailableError,
() => Effect.succeed(part),
),
)
: Effect.succeed(part),
)
Effect.forEach fails fast. If image.normalize throws Image.DecodeError (unsupported format) or Image.SizeError (cannot be resized below max_base64_bytes), the whole createUserMessage effect fails → promptSvc.prompt fails → the HTTP handler (httpapi/handlers/session.ts) maps it to a 400 Bad Request. The image message can never be sent.
Verified with the real @silvia-odwyer/photon-node@0.3.4 dependency: PhotonImage.new_from_byteslice throws for AVIF, HEIC, and BMP byte inputs, while PNG/JPEG/WebP decode fine.
The tool-result path (processor.ts) already handles this correctly with Effect.exit + filtering + an [N image omitted...] note. The user-message path is the asymmetric one.
Steps to Reproduce
- In the TUI, paste a local
.avif(or.heic/.bmp) image path — the TUI attachment picker explicitly accepts.avif(packages/tui/src/component/prompt/local-attachment.ts). - Send the prompt with the attached image.
- The request fails with HTTP 400; the message is never sent.
Impact
Any user with a modern camera/phone screenshot (HEIC) or an AVIF screenshot, or any image that cannot be compressed under the 5MB inline limit, hits a hard failure with no way to send the message at all.
Suggested Fix
Mirror the processor.ts pattern: catch normalize failures per-part (Effect.exit / Effect.catchAll), drop or replace the failing image with a synthetic text note, and keep the prompt alive.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.