{"record":{"id":"506b2ee3fec61fec","repo":"gildas-lormeau/SingleFile","slug":"response-error-506b2e","errorCode":null,"errorMessage":"response.error","messagePattern":"response\\.error","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/gdrive/gdrive.js","lineNumber":477,"sourceCode":"\t\tconst range = httpResponse.headers.get(\"Range\");\n\t\tif (range) {\n\t\t\tmediaUploader.offset = parseInt(range.match(/\\d+/g).pop(), 10) + 1;\n\t\t}\n\t\tif (mediaUploader.cancelled) {\n\t\t\tthrow new Error(\"upload_cancelled\");\n\t\t} else {\n\t\t\treturn sendFile(mediaUploader);\n\t\t}\n\t} else {\n\t\tgetResponse(httpResponse);\n\t}\n}\n\nasync function getJSON(httpResponse) {\n\thttpResponse = getResponse(httpResponse);\n\tconst response = await httpResponse.json();\n\tif (response.error) {\n\t\tthrow new Error(response.error);\n\t} else {\n\t\treturn response;\n\t}\n}\n\nfunction getResponse(httpResponse) {\n\tif (httpResponse.status == 200) {\n\t\treturn httpResponse;\n\t} else if (httpResponse.status == 404) {\n\t\tthrow new Error(\"path_not_found\");\n\t} else if (httpResponse.status == 401) {\n\t\tthrow new Error(\"invalid_token\");\n\t} else {\n\t\tthrow new Error(\"unknown_error (\" + httpResponse.status + \")\");\n\t}\n}\n","sourceCodeStart":459,"sourceCodeEnd":494,"githubUrl":"https://github.com/gildas-lormeau/SingleFile/blob/517fb7c5cf2096d89933b747e862d8ecf616a9f9/src/lib/gdrive/gdrive.js#L459-L494","documentation":"getJSON first validates the HTTP status via getResponse, then parses the JSON body; if the parsed body contains an `error` property, it throws that value as an Error. This surfaces Google Drive API structured error objects (e.g. {error: {code, message, errors: [...]}}) directly to the caller, so the thrown Error may not be a plain string message.","triggerScenarios":"Any call whose HTTP response is 2xx/acceptable but whose JSON body carries an error field — e.g. a Drive API error returned with an unexpected status that getResponse let through, or an endpoint returning 200 with an embedded error object.","commonSituations":"Drive API rate-limit or userRateLimitExceeded errors wrapped in JSON; malformed OAuth scopes producing an error body; API version changes that move error information into the body; catching the error and assuming message is a string when it is an object.","solutions":["Log/serialize the thrown error's message as JSON (response.error may be an object) to see code, message, and errors[].","Check the embedded error.errors[].reason for rate limiting and retry with exponential backoff if it is rateLimited/userRateLimitExceeded.","Verify the OAuth token's scopes cover the requested operation.","Confirm the endpoint URL and API version are current for the Drive v3 API."],"exampleFix":"// before\ncatch (e) { console.error(e.message); } // prints [object Object]\n// after\ncatch (e) {\n  const detail = typeof e.message === \"string\" ? e.message : JSON.stringify(e.message);\n  console.error(\"Drive API error:\", detail);\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isDriveErrorPayload(m) {\n  return m !== null && typeof m === \"object\" &&\n    ((typeof m.code === \"number\") || Array.isArray(m.errors) || typeof m.message === \"string\");\n}\n// usage\ncatch (e) { if (isDriveErrorPayload(e.message)) { handleDriveApiError(e.message); } else throw e; }","tryCatchPattern":"try { const data = await gdrive.getJSON(resp); }\ncatch (e) {\n  const payload = typeof e.message === \"string\" ? { message: e.message } : e.message;\n  if (payload && payload.errors && payload.errors[0] && payload.errors[0].reason === \"rateLimitExceeded\") {\n    return retryWithBackoff();\n  }\n  throw e;\n}","preventionTips":["Never assume e.message is a string from this library — normalize it first","Check error.errors[].reason for Drive-specific retry hints","Keep Google API usage under quota to avoid body-level errors"],"tags":["api-error","json","gdrive","google-api"],"backgroundTag":"api-error-response-body","analyzedSha":"517fb7c5cf2096d89933b747e862d8ecf616a9f9","analyzedAt":"2026-09-01T10:05:25.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}