openclaw - 💡(How to fix) Fix Web UI attachments are image-only end-to-end (UI picker + Gateway)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

The control-ui chat input only accepts image files, and the Gateway-side attachment normalizer silently drops anything non-image. Users cannot share PDFs, text files, or any non-image document through chat — even though the underlying Anthropic API supports document blocks for PDFs, and OpenClaw already implements a media://inbound/<id> mechanism for large attachments that could be generalized.

This is a single-flag-deep limitation in the UI, but a real feature gap in the Gateway pipeline.

Error Message

If the UI picker is patched locally to allow non-image files, the upload silently fails at the Gateway with no error surfaced to the user — a worse failure mode than the current up-front "no."

Root Cause

Fix Action

Workaround

For local-machine deployments where the agent has filesystem access, the agent's Read tool ingests files directly from disk — the user provides the path. Bypasses the picker and Gateway normalizer entirely. Not a fix.


RAW_BUFFERClick to expand / collapse

Summary

The control-ui chat input only accepts image files, and the Gateway-side attachment normalizer silently drops anything non-image. Users cannot share PDFs, text files, or any non-image document through chat — even though the underlying Anthropic API supports document blocks for PDFs, and OpenClaw already implements a media://inbound/<id> mechanism for large attachments that could be generalized.

This is a single-flag-deep limitation in the UI, but a real feature gap in the Gateway pipeline.

Repro

  1. Open the OpenClaw control UI chat
  2. Click the attachment button
  3. In the OS file picker, try to select a PDF (or any non-image file)
  4. The file is greyed out / unselectable

If the UI picker is patched locally to allow non-image files, the upload silently fails at the Gateway with no error surfaced to the user — a worse failure mode than the current up-front "no."

Root cause

Tested on [email protected].

Layer 1 — Web UI bundle

dist/control-ui/assets/index-Dba6JFRP.js:

  • Line 29H_=`image/*` defines the picker accept value
  • Line 29function U_(e){return typeof e==="string" && e.startsWith("image/")} is the MIME predicate
  • Line 568 — Two call sites of U_(e.type) gate both the file-pick handler and the drag-drop handler. Non-image files hit continue and are silently dropped.
  • Line 27function fp(e) (the serializer called before chat.send) hard-codes every attachment as {type:'image', mimeType, content} regardless of actual MIME.
  • Line 847accept=${H_} wires the input element.

UI display strings are also image-scoped (placeholder "paste more images...", attachment label "Image (${count})").

Layer 2 — Gateway attachment normalizer

dist/attachment-normalize-fsjzmyqL.js — the harder gate:

  • Lines 8–18MIME_TO_EXT is image-only
  • Lines 19–27SUPPORTED_OFFLOAD_MIMES is image-only (JPEG, PNG, WEBP, GIF, HEIC, HEIF)
  • Lines 187–193parseMessageWithAttachments sniffs MIME and explicitly drops non-images: "detected non-image (${sniffedMime}), dropping"
  • Line 199 — Throws on large non-image attachments
  • Lines 222–226 — Only emits {type:'image', data, mimeType} blocks downstream

Fixing only the UI picker doesn't help — the Gateway eats any non-image file silently.

Proposed fix

  1. UI bundle — broaden H_ (configurable allowlist or */*), drop the U_ MIME gate at both upload handlers, and have fp() set type based on actual MIME.
  2. Gateway normalizer — broaden MIME_TO_EXT and SUPPORTED_OFFLOAD_MIMES, replace the image-only drop in parseMessageWithAttachments with a typed dispatch.
  3. Output blocks — for application/pdf, emit Claude's type:'document' block (Anthropic SDK supports it natively). For arbitrary other types, reuse the existing media://inbound/<id> offload path and surface the resolved disk path to the agent.
  4. UI copy — make the "Image"/"images" strings type-agnostic.

Happy to PR this if a maintainer wants to weigh in on the design first.

Workaround

For local-machine deployments where the agent has filesystem access, the agent's Read tool ingests files directly from disk — the user provides the path. Bypasses the picker and Gateway normalizer entirely. Not a fix.


Meta: no in-product feedback channel

Filing this as part of the same issue because it's likely the upstream cause of papercuts going unfixed.

There is no openclaw feedback, openclaw report, or openclaw bug subcommand (openclaw --help confirms). No "Report a problem" affordance in the control UI. No first-party community channel surfaced anywhere in help output or onboarding. The only documented path from "user notices a real product limitation" to "maintainer sees it" is:

  1. User has a public GitHub account and is willing to file under it
  2. User reverse-engineers the bundled JS to identify file/line refs (or files a vague report that's harder to triage)
  3. User waits

For a self-hosted developer tool that's actively used, that's a hole — and it's actively shaping product quality, because the cost of reporting any papercut is high enough that most users won't bother. A relevant second instance of this same pattern: a workspace reset on 2026-04-20 silently wiped a fully-hatched agent imprint built over ~23 hours, with no reporter mechanism for the user to surface what happened. Same shape: irrecoverable loss + no reporting channel.

Even a minimal openclaw report subcommand that opens a templated GitHub issue in the browser, or a one-line "Report a problem" link in the control UI footer, would meaningfully shorten the feedback loop and surface this class of bug much earlier.

Happy to spin this out into its own issue if it's better tracked separately.

extent analysis

TL;DR

The most likely fix involves modifying the UI bundle to accept non-image files and updating the Gateway attachment normalizer to support various file types.

Guidance

  • Broaden the H_ variable in the UI bundle to accept non-image files by changing it to */* or implementing a configurable allowlist.
  • Update the fp() function to set the type based on the actual MIME type of the uploaded file.
  • Modify the Gateway attachment normalizer to support various file types by broadening MIME_TO_EXT and SUPPORTED_OFFLOAD_MIMES, and replacing the image-only drop in parseMessageWithAttachments with a typed dispatch.
  • Update the UI copy to make the "Image"/"images" strings type-agnostic.

Example

// Before
const H_ = 'image/*';

// After
const H_ = '*/*'; // or implement a configurable allowlist

// Before
function fp(e) {
  return { type: 'image', mimeType, content };
}

// After
function fp(e) {
  return { type: e.type, mimeType, content };
}

Notes

The proposed fix requires modifications to both the UI bundle and the Gateway attachment normalizer. Additionally, the UI copy needs to be updated to reflect the changes. The workaround mentioned in the issue is not a fix and only applies to local-machine deployments.

Recommendation

Apply the proposed fix to update the UI bundle and Gateway attachment normalizer to support various file types, as it addresses the root cause of the issue and provides a more robust solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING