fix(gemini): type mp4/mov/webm uploads so Gemini actually receives them - #332
Conversation
dcab67e to
a8591ed
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Gemini silently discards uploads it cannot type. Any extension missing from
GEMINI_UPLOAD_MIME_TYPES fell back to `application/octet-stream`, so the run
reported the file as attached (`files=1`) while the model answered as though
nothing had been sent.
That made video look unsupported when the upload path itself was fine.
Declaring `video/mp4` for the same MP4 works immediately: Gemini describes
the footage and quotes on-screen text.
Add only the three formats confirmed against the live endpoint, and pull the
lookup into an exported `resolveGeminiUploadMimeType` so it can be tested.
Probed each candidate with a sentinel prompt that distinguishes "received"
from "actually viewable":
.mp4 .mov .webm viewable - describe people, clothing and on-screen text
.avi received but not viewable; only echoed container metadata
.m4v dropped, despite identical bytes to a working .mp4 and
the same declared video/mp4 - the endpoint gates on the
extension too
.mkv .3gp .heic Gemini returns an error
.wav .mp3 .m4a never delivered, with audio/mpeg, audio/mp3, audio/wav
or audio/x-wav
.txt never delivered, with text/plain or text/md
So audio and plain text are not supported by this endpoint at all, and the
accepted set cannot be extrapolated from the Gemini API's documented formats.
Mapping them would advertise support that does not exist.
Note the 1 MB DEFAULT_MAX_FILE_SIZE_BYTES still applies; video generally
needs `--max-file-size-bytes` / ORACLE_MAX_FILE_SIZE_BYTES.
a8591ed to
4ddc53c
Compare
Manual hardened port of upstream PR steipete#332 (a8591ed), with end-to-end multipart and f.req coverage. Co-authored-by: Michal Kubenka <mkubenka@gmail.com>
|
Codex review: needs maintainer review before merge. Reviewed August 2, 2026, 1:36 PM ET / 17:36 UTC. ClawSweeper reviewWhat this changesMaps MP4, MOV, and WebM Gemini browser uploads to video MIME types, extracts the lookup into a testable resolver, and adds focused regression coverage. Merge readinessThis PR remains necessary: current Priority: P1 Review scores
Verification
How this fits togetherOracle’s Gemini browser adapter reads a local attachment, chooses its MIME type, uploads it to Gemini, and carries that type into the generation request. The mapping therefore determines whether an attached video is sent in a form the Gemini web endpoint can interpret. flowchart LR
A[CLI attachment path] --> B[Gemini browser adapter]
B --> C[MIME type resolver]
C --> D[Gemini upload request]
D --> E[Generation payload]
E --> F[Gemini model response]
Before merge
Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Merge the narrow, endpoint-verified video MIME mappings with their regression tests while retaining the generic fallback for formats not proven to work with Gemini’s web upload endpoint. Do we have a high-confidence way to reproduce the issue? Yes, from source and supplied live evidence: current Is this the best way to solve the issue? Yes: an extension-to-MIME mapping is the narrowest maintainable repair because the existing upload and generation paths already propagate the selected MIME type correctly. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against f5c087616b55. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (22 earlier review cycles; latest 8 shown)
|
|
Maintainer repair pushed through I reconciled the release note to the current Proof on the resulting branch:
Recommendation: LAND once the refreshed checks complete. |
The bug
GEMINI_UPLOAD_MIME_TYPEScovers only images and PDF. Everything else falls through toapplication/octet-stream, and Gemini silently discards uploads it cannot type.The failure is invisible from the outside, which is what makes it expensive:
The upload succeeds, the payload is built,
files=1is printed — and the model gets nothing. Reading the source reinforces the wrong conclusion, because the upload path genuinely is complete and correct. Only the MIME label is wrong.Declaring
video/mp4makes the same file work on the first attempt:The change
Adds exactly three entries —
.mp4,.mov,.webm— and extracts the lookup into an exportedresolveGeminiUploadMimeType()so it is unit-testable. No behaviour change for currently-mapped types; theapplication/octet-streamfallback is preserved.Why only three
I first wrote a much larger table from the Gemini API's documented formats, then probed each candidate against the live endpoint with a sentinel prompt separating "received" from "actually viewable". Most of it was wrong:
.mp4.mov.webm.aviLavf62.3.100).m4v.mp4and the same declaredvideo/mp4.mkv.3gp.heic.wav.mp3.m4aaudio/mpeg,audio/mp3,audio/wav,audio/x-wav.txttext/plainandtext/mdTwo conclusions worth recording:
.m4vcase is the proof: same bytes, samevideo/mp4, still dropped. So this table cannot be extrapolated from the Gemini API docs — each entry needs probing.I have kept the entries to what I verified. If you have a broader whitelist from the web app, more can be added safely.
Verification
Against
gemini-3.1-pro:NO VIDEO RECEIVED; after: accurate scene description plus verbatim on-screen subtitles, cross-checked against frames read locally.scale=640:-2,fps=8,crf 32). Answers to timestamp-specific questions matched an independently produced OCR transcript, including subtitles at 5:00 and 5:48 and both speakers' names.Checks:
vitest(5 new tests plus existingtests/gemini.test.ts— 15 passing),tsc --noEmit,oxfmt --check,oxlint.Notes for the maintainer
DEFAULT_MAX_FILE_SIZE_BYTESstill applies, so video realistically needs--max-file-size-bytes/ORACLE_MAX_FILE_SIZE_BYTES. Left alone as a separate policy decision.uploadGeminiFile()reads the whole file into a Buffer→Blob, so large media will exhaust the heap. Chunking is the practical answer; out of scope here.application/octet-streamarguably deserves a warning, since the current behaviour reports success while the model receives nothing — that is what made video look impossible rather than merely broken. There is no logger plumbed intoclient.ts's upload path, so I kept this PR to the data fix. Happy to follow up if you want the warning.