Skip to content

Commit ca97d60

Browse files
openrijalclaude
andcommitted
fix: fall back to git blobs api for github files larger than 1MB
The GitHub Contents API only returns the `content` field for files under 1MB. For files between 1-100 MB it responds with `type: 'file'` and `encoding: 'none'` but an empty `content`, causing the existing guard to throw `GitHub response is not a single file with content.` When `content` is missing, fetch the blob by sha via the Git Blobs API (`GET /repos/{owner}/{repo}/git/blobs/{sha}`), which streams base64 content up to 100 MB, then decode as before. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a527474 commit ca97d60

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

server/utils/githubContents.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,41 @@ export async function getGithubJsonFile<T = unknown>(
4646
statusMessage: body?.message || `GitHub API error (${res.status})`,
4747
})
4848
}
49-
if (body.type !== 'file' || !body.content || !body.sha) {
49+
if (body.type !== 'file' || !body.sha) {
5050
throw createError({
5151
statusCode: 500,
5252
statusMessage: 'GitHub response is not a single file with content.',
5353
})
5454
}
55-
const decoded = Buffer.from(body.content.replace(/\n/g, ''), 'base64').toString('utf8')
55+
// The Contents API omits `content` for files >1MB (returns encoding "none").
56+
// Fall back to the Git Blobs API, which streams base64 content up to 100MB.
57+
let base64Content: string | undefined = body.content
58+
if (!base64Content || body.encoding === 'none') {
59+
const blobUrl = `https://api.github.com/repos/${owner}/${repo}/git/blobs/${body.sha}`
60+
const blobRes = await fetch(blobUrl, { headers: authHeaders(token) })
61+
const blobText = await blobRes.text()
62+
let blobBody: any
63+
try {
64+
blobBody = JSON.parse(blobText)
65+
}
66+
catch {
67+
blobBody = { message: blobText }
68+
}
69+
if (!blobRes.ok) {
70+
throw createError({
71+
statusCode: blobRes.status >= 500 ? 502 : 400,
72+
statusMessage: blobBody?.message || `GitHub Blobs API error (${blobRes.status})`,
73+
})
74+
}
75+
if (blobBody.encoding !== 'base64' || typeof blobBody.content !== 'string') {
76+
throw createError({
77+
statusCode: 500,
78+
statusMessage: 'GitHub Blobs API response is missing base64 content.',
79+
})
80+
}
81+
base64Content = blobBody.content
82+
}
83+
const decoded = Buffer.from(base64Content!.replace(/\n/g, ''), 'base64').toString('utf8')
5684
let parsed: T
5785
try {
5886
parsed = JSON.parse(decoded) as T

0 commit comments

Comments
 (0)