{"record":{"id":"8d0c1b812ead9c2d","repo":"gildas-lormeau/SingleFile","slug":"responsedata-message","errorCode":null,"errorMessage":"responseData.message","messagePattern":"responseData\\.message","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/github/github.js","lineNumber":134,"sourceCode":"\t\t\t\t\treturn responseData;\n\t\t\t\t} else if (filenameConflictAction == CONFLICT_ACTION_PROMPT) {\n\t\t\t\t\tif (prompt) {\n\t\t\t\t\t\tpath = await prompt(path);\n\t\t\t\t\t\tif (path) {\n\t\t\t\t\t\t\treturn await createContent({ path, content, message });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn responseData;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\toptions.filenameConflictAction = CONFLICT_ACTION_UNIQUIFY;\n\t\t\t\t\t\treturn await createContent({ path, content, message });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (response.status < 400) {\n\t\t\t\treturn responseData;\n\t\t\t} else {\n\t\t\t\tthrow new Error(responseData.message);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error.name != ABORT_ERROR_NAME) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tfunction fetchContentData(method, body) {\n\t\t\treturn fetch(`${GITHUB_API_URL}/${REPOS_PATH}/${userName}/${repositoryName}/${CONTENTS_PATH}/${path}`, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tsignal\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction splitFilename(filename) {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/gildas-lormeau/SingleFile/blob/517fb7c5cf2096d89933b747e862d8ecf616a9f9/src/lib/github/github.js#L116-L152","documentation":"createContent throws an Error whose message is the GitHub API's `message` field from the JSON response body when the HTTP status is >= 400. This surfaces GitHub's own error text (e.g. \"Bad credentials\", \"Not Found\", \"name already exists on the same branch\", \"API rate limit exceeded\") directly to the caller.","triggerScenarios":"Uploading/creating a file where status >= 400: 401 bad or expired personal access token; 404 repo or branch/path does not exist; 422 commit conflict because the file changed and no SHA was supplied for update; 403 rate limit or resource not accessible.","commonSituations":"Token expired or rotated causing \"Bad credentials\"; writing to a repo path where the file already exists without passing its blob SHA (must use update); private repo with a fine-grained token lacking Contents write permission; hitting the 5000 req/hr REST limit in CI loops.","solutions":["Log the error message to see GitHub's exact reason; branch on it (credentials vs not-found vs conflict vs rate limit).","For \"already exists\" conflicts, fetch the current file's SHA and pass it to update the content instead of creating.","For 401, regenerate the PAT/refresh the token and ensure required scopes (repo / Contents: write for fine-grained tokens).","For 403 rate limit, add backoff and reduce request volume; check X-RateLimit-Remaining headers.","Verify repo name, branch, and path spelling and that the branch exists."],"exampleFix":"// before\nawait github.createContent({...}); // Error: sha wasn't supplied\n// after\ntry {\n  await github.createContent({..., content, message});\n} catch (e) {\n  if (/already exists|sha wasn't supplied/i.test(e.message)) {\n    const existing = await github.getFileSha(path);\n    await github.createContent({..., sha: existing.sha});\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight checks before createContent\nif (!token || token.length < 20) throw new Error(\"GitHub token missing/short\");\nif (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) throw new Error(\"repo must be owner/name\");\n// check whether the file already exists to fetch its SHA for updates","typeGuard":null,"tryCatchPattern":"try { await github.createContent(params); }\ncatch (e) {\n  const msg = String(e.message);\n  if (/Bad credentials/i.test(msg)) return reauthGitHub();\n  if (/Not Found/i.test(msg)) return verifyRepoAndBranch();\n  if (/already exists|sha/i.test(msg)) return updateWithSha(params);\n  if (/rate limit/i.test(msg)) return retryWithBackoff();\n  throw e;\n}","preventionTips":["Fetch the existing file's SHA before writing over an existing path","Check X-RateLimit-Remaining and back off before hitting limits","Use fine-grained PATs with Contents: write for private repos","Rotate/validate tokens in CI before runs"],"tags":["github-api","http-error","rest-api","token"],"backgroundTag":"github-api-error-response","analyzedSha":"517fb7c5cf2096d89933b747e862d8ecf616a9f9","analyzedAt":"2026-09-01T10:05:25.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}