[BUG] Drive MCP `create_file` silently truncates binary uploads around 10K base64 chars
[BUG] Drive MCP create_file silently truncates binary uploads around 10K base64 chars
Summary
The Drive MCP create_file tool silently truncates large binary uploads. A 12 KB multi-sheet xlsx (16,016 base64 chars) uploaded with mimeType: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet arrives in Drive as 8,447 bytes — the first 5 of 13 zip entries intact, central directory chopped off entirely. Google Sheets then refuses to open it ("File could not open. Try refreshing the page."). The tool returns a successful response with a valid id and viewUrl — there's no error, no warning, no size field in the response that would let the caller detect the truncation.
Intermediate payload sizes also fail but with a different bogus error: a 7,223-byte xlsx (9,632 base64 chars, generated by Python base64.b64encode) is rejected outright with "The file content is not a valid base64 string." even though it's perfectly valid base64.
Repro
- Generate any multi-tab xlsx locally (~12 KB, e.g. 5 sheets with a few hundred cells total).
- Base64-encode the bytes → 16K-char string.
- Call
create_filewithmimeType: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, the base64content, and aparentId. - Tool returns
{id, title, viewUrl}— looks like success. get_file_metadataon the returned id reportsfileSize: "8447"(the original was 12,012).- Download the bytes back with
download_file_contentand diff against the local source: first 582 bytes match exactly, then the file just ends mid-deflate-stream insidexl/theme/theme1.xml. - Opening in Google Sheets → "File could not open. Try refreshing the page." Same in Excel.
Size cliff (bounded experimentally)
| Payload bytes | Base64 chars | Behaviour |
|---|---|---|
| ~6,500 | ~8,700 | ✅ Uploads intact |
| 7,223 | 9,632 | ❌ Rejected: "The file content is not a valid base64 string." |
| 12,012 | 16,016 | ❌ Silently truncated to 8,447 B |
| 8,024 (CSV, text/csv) | 10,700 | ✅ Uploads intact, auto-converts to native Sheet |
The text/csv conversion path is more lenient than the binary-blob path. The cliff for binary uploads is somewhere in 9.5K–11K base64 chars, with two different failure modes on either side.
Impact
- Anyone uploading a real-world xlsx / pptx / pdf (or any multi-KB binary) via this tool hits the bug. These are the exact file types users most commonly generate in Cowork workflows.
- Completely silent to the caller: only way to detect is to download the bytes back and inspect. In practice this means the LLM tells the user "here's your file" and the user reports back "I can't open it."
- The 9.6K-b64 "not a valid base64 string" error is actively misleading — it makes callers assume encoding problems when the encoding is fine.
Suggested fixes
- Fix the underlying limit. A 12 KB binary upload is small. Whatever the real cap is, it should comfortably exceed ordinary files.
- If there's a hard limit, fail loudly with
PayloadTooLargeError: content exceeds N bytesinstead of silently truncating. - Return
fileSize/ checksum in thecreate_fileresponse so callers can client-side verifylen(decoded_content) == response.fileSize. - Document the cap in the tool description. "Max content size: N KB" in the JSONSchema would save a lot of wasted debugging.
- Consider resumable / chunked upload under the hood for non-trivial binary payloads — the Drive v3 API already supports this (
uploadType=resumable).
Workaround (for anyone hitting this)
Pivot xlsx/multi-tab outputs to one CSV per tab, upload each with mimeType: "text/csv". The Drive MCP auto-converts text/csv to a native Google Sheet server-side. Trade-off is five Sheets instead of one workbook, but the uploads actually work.
Context
- Hit this while building a personal skill that emits a 5-tab xlsx (tour-date overlap finder). Every single run was producing a corrupt Sheet in Drive; took an hour of byte-level diffing to realise the tool was lying about success.
- Repro artifact ID (valid locally, corrupt in Drive):
1n6mVgT4Zz9BUlZaBP0V51pY8BBfRa2mh— happy to share binary dumps if it'd help triage.
10 Comments
Drive MCP
create_filesilently truncating binary uploads above ~8K bytes — returning success with a valid ID while delivering a corrupt file — is a data integrity failure that is worse than an explicit error. The caller has no way to detect the truncation from the response.The size cliff you identified experimentally is the key diagnostic: ~8,700 base64 chars (≈6,500 bytes) succeeds intact, ~9,632 chars gets a false "not valid base64" error, and ~16,016 chars silently truncates. This pattern suggests there is a hard limit somewhere in the MCP tool's content handling (possibly a JSON field size limit, an HTTP request body limit, or a string buffer limit at ~8-9K chars).
The likely cause: The MCP protocol JSON body for
create_filecontains the base64 content as a string field. JSON string size limits or HTTP body limits in the MCP transport layer may be truncating the content without surfacing an error — the truncated content is still valid UTF-8 (base64 is ASCII), so no parse error fires.The fix has two parts:
create_fileresponse should include auploadedBytesfield that the caller can compare against the expected size. IfuploadedBytes < encodedSize, the caller knows the upload was truncated.Immediate workaround: Limit binary uploads to the known-safe range (~6,500 bytes / ~8,700 base64 chars) and split larger files into separate uploads, or use Drive's import feature for Office files rather than direct binary upload.
Hitting the same bug with .docx uploads — adding evidence to confirm the
issue isn't xlsx-specific:
the OP's 9.6K-char rejection case (so the rejection threshold extends
upward at least to 15.5K chars, not just a narrow band)
reports byte-identical
the exact same encoding pipeline
Use case: an automated meeting-notes pipeline that generates formatted .docx
files for Google Drive. Every typical-sized output blocks on this bug.
Confirms the cliff is real for any binary office format (xlsx, docx, presumably
pptx), not just spreadsheets. +1 on all five suggested fixes — especially
returning fileSize in the create_file response so callers can verify.
+1 confirming, different mime type.
Repro:
Same connector, same failure shape, not xlsx-specific.
Adjacent finding worth flagging here, since it's the same "silent corruption with no error signal" pattern the issue calls out: without
disableConversionToGoogleType: true, even a tiny valid PNG (1×1, 92 base64 chars) is silently routed through Drive's auto-conversion path and becomes an empty application/vnd.google-apps.document (fileSize: 1) with no error and a viewUrl pointing at an empty Google Doc shell. Setting the flag is effectively mandatory just to attempt a real binary upload — and once you do, the size cap you describe is the next wall.So binary uploads through this MCP have at least two failure modes stacked: (1) silent conversion to an empty Google Doc when
disableConversionToGoogleTypeis omitted, regardless of size; (2) the truncation/false-invalid-base64 errors you document above the ~10–16K char threshold. Both produce success-shaped responses for small inputs, no surface area to detect corruption from the agent side.Hitting the same bug from a different angle — adding it here in case it helps triangulate the root cause.
Different manifestation: silent byte substitution well below the cliff documented above
sharedStrings.xml)mcp__claude_ai_Google_Drive__create_filewithcontentMimeType: application/vnd.openxmlformats-officedocument.spreadsheetml.sheetWhat I see:
create_filereturns success with a validid.get_file_metadatareports the correct size (6,127 bytes — same as local source).download_file_contentreturns 6,127 bytes — same size as upload.unzip -ton the downloaded file fails: three.xmlentries fail to inflate (invalid compressed data), one CRC mismatch. Sheets refuses to open it ("File could not open").Diff'ing the base64 strings (sent vs returned) shows 12 character substitutions — all replacements are themselves valid base64 chars (
0→1,1→l,t→u,5→+, etc.), and the largest cluster is 9 contiguous chars rewritten. The substitutions are deterministic — uploading the same b64 twice produces files with the same corrupted MD5.Why this matters
Strongly seconding the suggested fixes in the issue body, especially:
create_fileresponse.Repro file available on request.
Confirming this is still broken as of late May 2026. Blocking an agentic Claude Code workflow that updates an .xlsx tracker file on a recurring schedule via /schedule — the truncation forces a manual download/merge step that defeats automation entirely.
CSV-per-tab workaround doesn't fit my use case (fill colors and in-cell comments are load-bearing). Resumable upload above ~256 KB (as proposed earlier in this thread) would unblock this. Happy to test a fix when one lands.
Still relevant in my case, both docx and xlsx.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
We hit this exact bug in production in August 2026, four months after this report — it is still unfixed, and this issue appears to have been auto-closed as stale rather than resolved. Requesting a reopen: here are fresh measurements that also show the failure envelope has shifted over time, which makes it worse, not better (no client-side "safe size" heuristic can be trusted).
Upload direction (
create_file, base64 PDF test files, 2026-08-06):| Payload | Result |
|---|---|
| 5 KB | ✅ uploaded, exact size |
| 15 KB | ✅ uploaded, exact size |
| 25 KB | ⚠️ uploaded with exact size, but a round-trip hash check found 1 character corrupted out of ~34,000 — silent corruption that
fileSizecannot detect || 50 KB | ❌ impossible (base64 exceeds single-response output limits; no chunked/resumable upload available) |
Real-world incident (2026-08-05): a 12,135-byte .xlsx arrived on Drive as 8,424 bytes — same signature as the OP (12 KB → 8,447 B): success response with valid
idandviewUrl, correct name/icon/extension, zip central directory chopped off, discovered only on open. Since the connector exposes no delete or overwrite, the corrupted file then sits in the destination folder until a human removes it manually.Download direction (2026-08-07): the same class of failure affects
download_file_content. A 12,155-byte .xlsx (16,208 expected base64 chars) came through as 12,712 chars — truncated, unreadable zip.Note the thresholds do not match the OP's April measurements (failures already at ~7 KB then; 15 KB clean for us now, 25 KB corrupted): the limit is not stable across time/conditions.
The OP's proposed fixes are exactly right: (1) fail loudly instead of returning success on a truncated write, (2) return
fileSize/checksum in thecreate_fileresponse, (3) document the limit in the tool schema, (4) chunked/resumable upload (Drive v3 supports it).The read-side sibling of this bug (silent truncation of the Google Sheets markdown rendering at ~2,400–2,500 cells per tab, no marker) is now reported at anthropics/claude-ai-mcp#805. Also related here: #54137.
It still reproduces for me.
Yes, we need some activity with fixing it, not closing.
Why we need new issue, this one is describing the problem well.
This class of bug shows up when file bytes go through the model or JSON. Upload by URL or path and return a download URL instead.
Hosted MCP that does that: https://mcp.beecargo.net/mcp (
beecargo_upload). Guest bootstrap is/mcp/guestif/mcpasks for auth.