{"record":{"id":"7dd01d950471845e","repo":"badges/shields","slug":"undecodable-content","errorCode":null,"errorMessage":"undecodable content","messagePattern":"undecodable content","errorType":"exception","errorClass":"InvalidResponse","httpStatus":424,"severity":"error","filePath":"services/github/github-common-fetch.js","lineNumber":43,"sourceCode":"async function fetchRepoContent(\n  serviceInstance,\n  { user, repo, branch = 'HEAD', filename },\n) {\n  const httpErrors = httpErrorsFor(\n    `repo not found, branch not found, or ${filename} missing`,\n  )\n  if (serviceInstance.staticAuthConfigured) {\n    const { content } = await serviceInstance._requestJson({\n      schema: contentSchema,\n      url: `/repos/${user}/${repo}/contents/${filename}`,\n      options: { searchParams: { ref: branch } },\n      httpErrors,\n    })\n\n    try {\n      return Buffer.from(content, 'base64').toString('utf-8')\n    } catch (e) {\n      throw new InvalidResponse({ prettyMessage: 'undecodable content' })\n    }\n  } else {\n    const { buffer } = await serviceInstance._request({\n      url: `https://raw.githubusercontent.com/${user}/${repo}/${branch}/${filename}`,\n      httpErrors,\n    })\n    return buffer\n  }\n}\n\nasync function fetchJsonFromRepo(\n  serviceInstance,\n  { schema, user, repo, branch = 'HEAD', filename },\n) {\n  if (serviceInstance.staticAuthConfigured) {\n    const buffer = await fetchRepoContent(serviceInstance, {\n      user,\n      repo,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/github/github-common-fetch.js#L25-L61","documentation":"fetchRepoContent() decodes GitHub's base64-encoded file content to UTF-8 and wraps any decoding failure in InvalidResponse 'undecodable content'. It is thrown when Buffer.from(content, 'base64')/toString produces or receives data that cannot be handled, meaning the repository file content isn't valid base64 or the expected shape changed. Treat it as an upstream data problem, not a bug in your request parameters.","triggerScenarios":"Requesting a file's content through the GitHub contents API (GraphQL or REST path used by configContent/buffer/content) where the returned `content` field is not valid base64 — e.g. file larger than 1MB so GitHub returns content: null, an empty string, or a malformed payload.","commonSituations":"Pointing the service at a file >1MB (contents API truncates/omits base64 content); binary files fetched via a route expecting base64 JSON; GitHub API response shape changes; requesting a file that is actually a Git LFS pointer in an unexpected path.","solutions":["Confirm the target file is under 1MB, or use the raw.githubusercontent.com / Git blobs API for large files.","Retry the request — transient API issues can return incomplete payloads.","Check that the requested file exists and is a regular text file, not a submodule, symlink, or directory listing."],"exampleFix":"// before: fetching a 2MB config through the contents API\n/service/github/user/repo/config/large-config.json\n// after: keep tracked config files under 1MB or use raw content","handlingStrategy":"try-catch","validationCode":"// pre-check file size via the contents API metadata\nconst meta = await fetch('https://api.github.com/repos/OWNER/REPO/contents/' + path).then(r => r.json());\nif (meta.size > 1000000) throw new Error('file too large for base64 contents API');","typeGuard":"function isDecodableContent(content) {\n  return typeof content === 'string' && content.length > 0 && /^[A-Za-z0-9+/=\\s]+$/.test(content);\n}","tryCatchPattern":"try {\n  const text = await fetchRepoContent({ user, repo, filename, branch });\n} catch (e) {\n  if (e.prettyMessage === 'undecodable content') {\n    // fall back to raw.githubusercontent.com or the git blobs API\n  } else throw e;\n}","preventionTips":["Keep files fetched via the contents API under 1MB.","Prefer the raw endpoint for large or binary files.","Handle content: null in GitHub API responses before decoding."],"tags":["github","invalid-response","base64","encoding"],"backgroundTag":"undecodable-content","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}