[BUG] Drive MCP `create_file` silently truncates binary uploads around 10K base64 chars

Open 💬 6 comments Opened Apr 18, 2026 by siewkumhong

[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

  1. Generate any multi-tab xlsx locally (~12 KB, e.g. 5 sheets with a few hundred cells total).
  2. Base64-encode the bytes → 16K-char string.
  3. Call create_file with mimeType: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, the base64 content, and a parentId.
  4. Tool returns {id, title, viewUrl} — looks like success.
  5. get_file_metadata on the returned id reports fileSize: "8447" (the original was 12,012).
  6. Download the bytes back with download_file_content and diff against the local source: first 582 bytes match exactly, then the file just ends mid-deflate-stream inside xl/theme/theme1.xml.
  7. 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

  1. Fix the underlying limit. A 12 KB binary upload is small. Whatever the real cap is, it should comfortably exceed ordinary files.
  2. If there's a hard limit, fail loudly with PayloadTooLargeError: content exceeds N bytes instead of silently truncating.
  3. Return fileSize / checksum in the create_file response so callers can client-side verify len(decoded_content) == response.fileSize.
  4. Document the cap in the tool description. "Max content size: N KB" in the JSONSchema would save a lot of wasted debugging.
  5. 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.

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗