{"record":{"id":"2b8e6dc55dc2f629","repo":"yamadashy/repomix","slug":"access-denied-the-repository-might-be-private-or","errorCode":null,"errorMessage":"Access denied. The repository might be private or you might not have permission to access it.","messagePattern":"Access denied\\. The repository might be private or you might not have permission to access it\\.","errorType":"http","errorClass":"RepomixError","httpStatus":403,"severity":"error","filePath":"src/core/git/gitHubArchiveApi.ts","lineNumber":56,"sourceCode":" * Checks if a response indicates a GitHub API rate limit or error\n */\nexport const checkGitHubResponse = (response: Response): void => {\n  if (response.status === 404) {\n    throw new RepomixError(\n      'Repository not found or is private. Please check the repository URL and your access permissions.',\n    );\n  }\n\n  if (response.status === 403) {\n    const rateLimitRemaining = response.headers.get('X-RateLimit-Remaining');\n    if (rateLimitRemaining === '0') {\n      const resetTime = response.headers.get('X-RateLimit-Reset');\n      const resetDate = resetTime ? new Date(Number.parseInt(resetTime, 10) * 1000) : null;\n      throw new RepomixError(\n        `GitHub API rate limit exceeded. ${resetDate ? `Rate limit resets at ${resetDate.toISOString()}` : 'Please try again later.'}`,\n      );\n    }\n    throw new RepomixError(\n      'Access denied. The repository might be private or you might not have permission to access it.',\n    );\n  }\n\n  if (response.status === 500 || response.status === 502 || response.status === 503 || response.status === 504) {\n    throw new RepomixError('GitHub server error. Please try again later.');\n  }\n\n  if (!response.ok) {\n    throw new RepomixError(`GitHub API error: ${response.status} ${response.statusText}`);\n  }\n};\n","sourceCodeStart":38,"sourceCodeEnd":69,"githubUrl":"https://github.com/yamadashy/repomix/blob/f465ad909315a22120636baf03fa5e28701a50cb/src/core/git/gitHubArchiveApi.ts#L38-L69","documentation":"A 403 from GitHub that is NOT a rate limit (X-RateLimit-Remaining is not '0') means GitHub refused authorization: the token or anonymous identity lacks permission for the repository. This is distinct from the rate-limit 403 and from 404.","triggerScenarios":"GitHub API/archive request returns HTTP 403 with X-RateLimit-Remaining != '0' — the supplied GITHUB_TOKEN is invalid/expired/revoked, lacks the repo scope, or the repo belongs to an org with IP allow-list/SSO enforcement.","commonSituations":"Expired or rotated token still set in the environment; classic PAT without the 'repo' scope for private repos; fine-grained token without read contents permission; org SSO not authorized for the token; org IP allow-list blocking the runner.","solutions":["Check the token: `curl -H \"Authorization: Bearer $GITHUB_TOKEN\" https://api.github.com/user` — if it fails, generate a new token with repo read access.","Grant the token the required scopes (classic: 'repo'; fine-grained: Contents: read for that repository).","Authorize the token for the organization via SSO (Settings → Developer settings → token → 'Configure SSO').","If an org IP allow-list is active, run from an allow-listed network or ask an admin to allow your IP."],"exampleFix":"// before (token without repo scope)\nexport GITHUB_TOKEN=ghp_readOnlyPublicToken\nnpx repomix --remote https://github.com/myorg/private-repo\n// after — regenerate with repo scope\nexport GITHUB_TOKEN=ghp_newTokenWithRepoScope\nnpx repomix --remote https://github.com/myorg/private-repo","handlingStrategy":"try-catch","validationCode":"const res = await fetch('https://api.github.com/repos/owner/repo', {\n  headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` }\n});\nif (res.status === 403) throw new Error('Token lacks permission for this repo; check scopes/SSO.');","typeGuard":null,"tryCatchPattern":"try {\n  await pack({ remote: url });\n} catch (e) {\n  if (e instanceof RepomixError && e.message.includes('Access denied')) {\n    console.error('Fix token scopes/SSO or use an account with access to the repo.');\n  } else throw e;\n}","preventionTips":["Validate the token with `curl -H \"Authorization: Bearer $GITHUB_TOKEN\" https://api.github.com/user` before runs.","Grant classic tokens the 'repo' scope (or fine-grained tokens Contents: read) for private repositories.","Configure SSO for org-scoped tokens and keep org IP allow-lists updated for CI runners.","Rotate tokens before expiry and avoid committing stale tokens in env files."],"tags":["github","http-403","authentication","permissions"],"backgroundTag":"access-denied","analyzedSha":"f465ad909315a22120636baf03fa5e28701a50cb","analyzedAt":"2026-08-29T01:27:42.024Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}