[BUG] GitHub connector: get_file_contents reports "successfully downloaded text file" but returns `[non-text content: resource]` with no file body (get_commit full_patch returns the same content fine)
Summary
In a claude.ai session using the GitHub connector, get_file_contents reports a successful download and then returns no file body. The tool result is:
successfully downloaded text file (SHA: <40-hex blob sha>)
[non-text content: resource]
The files are plain UTF-8 Markdown. Nothing about them is non-text.
Because the call reports success, there is no error to catch. From the model's side the file simply arrives empty, which is indistinguishable from an empty file.
Steps to reproduce
- Connect GitHub Integration on claude.ai (OAuth, account with access to a private repo).
- In a conversation, call
get_file_contentson a UTF-8 Markdown file in that private repo. - Observe the result.
Observed
Three calls, two different private repos, three different Markdown files (~8–12 KB each, ASCII plus a few UTF-8 punctuation characters — em dashes, §, curly quotes). All three returned the same thing: a success line carrying a plausible 40-hex blob SHA, followed by [non-text content: resource] and no content.
Blob SHAs from two of the failing calls, in case they help correlate server-side logs:
5aaca3b4fb66240a790492fd16a3899f9c6ad34d52f69c0540c35c0fdb4ac4a3f78e926c8d3276d2
Retrying, pinning ref to an explicit commit SHA instead of the default branch, and requesting the same path a second time all produce the identical result.
Expected
Either the file body, or an error that says the body could not be delivered. A success message with no payload is the worst of the three.
Scope — what still works
This appears specific to the blob-read path. In the same session, on the same repos, immediately before and after the failing calls:
list_commits— works, full JSON.get_commitwithdetail: "full_patch"— works, and returns the complete unified diff text, including the exact lines of the files thatget_file_contentsrefuses to hand over.
So the content is reachable through the connector. It is only the file-content endpoint that drops it.
Workaround, and why it is not a fix
Since the patches come through, a file can be rebuilt by replaying its commit history from the initial commit forward. I did this successfully for one ~250-line Markdown file: 16 commits, roughly 20 tool calls, and the reconstruction can be verified byte-exact by recomputing the git blob SHA (sha1("blob " + len + "\0" + content)) and comparing it to the SHA the connector reports.
It works. It is also expensive, scales with a file's history rather than its size, and produces a reconstruction rather than a read — which matters for any workflow where the file is an instruction or policy document that is supposed to be fetched verbatim.
Impact
Agent setups that bootstrap by fetching committed instruction files from a repo cannot boot. In my case a chain of files — each pointing to the next — is unreadable end to end, and the intended failure behaviour (stop and report, do not run from memory) is the correct response but leaves the session unable to do anything. The reconstruction workaround costs more per file than the work the session was meant to do.
Environment
- claude.ai, mobile and web
- GitHub Integration connector via OAuth, showing Connected
- Private repos on the authenticated account, connector has read access
- Tool calls issued in-conversation; no Claude Code involved
Related
Possibly adjacent to the cluster of connector-transport issues (#93956 tool calls dropped in transit, #94532 GitHub tools absent despite Connected), though this one differs in an important way: the call is delivered, executed, and reports success — it computes a real blob SHA — and only the payload goes missing.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗