{"record":{"id":"40caf31456aed207","repo":"Mintplex-Labs/anything-llm","slug":"res-reason","errorCode":null,"errorMessage":"${res.reason}","messagePattern":"\\$\\{res\\.reason\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"frontend/src/models/dataConnector.js","lineNumber":16,"sourceCode":"import { API_BASE } from \"@/utils/constants\";\nimport { baseHeaders } from \"@/utils/request\";\nimport showToast from \"@/utils/toast\";\n\nconst DataConnector = {\n  github: {\n    branches: async ({ repo, accessToken }) => {\n      return await fetch(`${API_BASE}/ext/github/branches`, {\n        method: \"POST\",\n        headers: baseHeaders(),\n        cache: \"force-cache\",\n        body: JSON.stringify({ repo, accessToken }),\n      })\n        .then((res) => res.json())\n        .then((res) => {\n          if (!res.success) throw new Error(res.reason);\n          return res.data;\n        })\n        .then((data) => {\n          return { branches: data?.branches || [], error: null };\n        })\n        .catch((e) => {\n          console.error(e);\n          showToast(e.message, \"error\");\n          return { branches: [], error: e.message };\n        });\n    },\n    collect: async function ({ repo, accessToken, branch, ignorePaths = [] }) {\n      return await fetch(`${API_BASE}/ext/github/repo`, {\n        method: \"POST\",\n        headers: baseHeaders(),\n        body: JSON.stringify({ repo, accessToken, branch, ignorePaths }),\n      })\n        .then((res) => res.json())","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/frontend/src/models/dataConnector.js#L1-L34","documentation":"Thrown by DataConnector.github.branches when the backend proxy at /ext/github/branches returns JSON with success:false. The thrown message is res.reason, which the backend is expected to populate with the underlying GitHub API failure (bad credentials, repo not found, rate limit). The .catch logs, toasts, and returns {branches:[], error} so the UI degrades to an empty list rather than crashing. Note: if the backend omits reason, new Error(undefined) yields an empty message.","triggerScenarios":"Wrong or revoked GitHub access token; a repo string that does not exist or that the token cannot access; GitHub primary or secondary rate limit; backend cannot reach api.github.com.","commonSituations":"Classic PAT expired or lacked repo scope; repo typed as 'owner/name' with a typo; fine-grained PAT missing 'contents: read'; backend running in a region that hit GitHub's abuse rate limit.","solutions":["Confirm the access token still has 'repo' (classic) or 'contents: read' (fine-grained) scope.","Verify the repo string is exactly 'owner/name' and visible to the token owner.","If res.reason mentions 'rate limit', wait for the window reset before retrying.","Inspect backend logs - the proxy may be failing before it ever calls GitHub."],"exampleFix":"// before\nconst { branches } = await DataConnector.github.branches({ repo, accessToken });\n\n// after\nconst { branches, error } = await DataConnector.github.branches({ repo, accessToken });\nif (error) showToast(`GitHub branches: ${error}`, 'error');\nreturn branches;","handlingStrategy":"validation","validationCode":"function validateGithubArgs({ repo, accessToken }) {\n  if (!/^[-.\\w]+\\/[-.\\w]+$/.test(repo ?? ''))\n    return 'repo must be \"owner/name\"';\n  if (!accessToken || accessToken.length < 20)\n    return 'accessToken looks invalid';\n  return null;\n}","typeGuard":"/** @param {unknown} r */\nfunction isBranchesResult(r) {\n  return typeof r === 'object' && r !== null\n    && Array.isArray(r.branches)\n    && (r.error === null || typeof r.error === 'string');\n}","tryCatchPattern":"const result = await DataConnector.github.branches({ repo, accessToken });\nif (result.error) {\n  showRetryableToast(result.error);\n  return [];\n}\nreturn result.branches;","preventionTips":["Validate the 'owner/name' format client-side to avoid a wasted round-trip.","Cache branch lists (the call already uses force-cache) and invalidate on repo change.","Prefer fine-grained PATs scoped to the minimum needed repository.","Treat an empty branches array with a non-null error as a failure, not success."],"tags":["api","data-connector","github","auth","rate-limit"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}