coleam00/Archon · error
Authentication failed for ${owner}/${repo}. ${authHint}
Error message
Authentication failed for ${owner}/${repo}. ${authHint} What it means
Thrown by GitHubAdapter.ensureRepoReady when cloneRepository returns code 'permission_denied': the repository exists but the credentials used for the clone were rejected or lack read access. The message includes an auth-specific hint depending on whether Archon is running in GitHub App mode or PAT mode (GITHUB_TOKEN).
Source
Thrown at packages/adapters/src/forge/github/adapter.ts:766
ghToken ? { token: ghToken } : undefined
);
if (!cloneResult.ok) {
getLog().error(
{ error: cloneResult.error, owner, repo, repoPath },
'github.repo_clone_failed'
);
if (cloneResult.error.code === 'not_a_repo') {
throw new Error(
`Repository ${owner}/${repo} not found or is private. Check repository access.`
);
} else if (cloneResult.error.code === 'permission_denied') {
const authHint =
this.auth.kind === 'app'
? 'Check that the Archon GitHub App is installed on the org and has the Contents:Read permission.'
: 'Check GITHUB_TOKEN permissions.';
throw new Error(`Authentication failed for ${owner}/${repo}. ${authHint}`);
}
throw new Error(
`Failed to clone ${owner}/${repo}: ${'message' in cloneResult.error ? cloneResult.error.message : cloneResult.error.code}`
);
}
await addSafeDirectory(toRepoPath(repoPath));
// App mode: install the git credential helper on the newly cloned worktree
// so workflows that outlive the 1h installation-token expiry can refresh
// credentials in-place. Non-fatal — workflows that complete in <1h still
// succeed via the URL-embedded token from the clone above. The result
// discriminator tells us whether the install actually happened so we
// don't log a false "installed" line in builds where the helper script
// isn't on disk.
if (this.auth.kind === 'app') {
const result = await installCredentialHelper(repoPath);
switch (result.kind) {View on GitHub (pinned to 0773b97458)
Solutions
- In App mode: verify the Archon GitHub App is installed on the org and granted Contents (Read) permission, then retry so a fresh ~1h installation token is minted.
- In PAT mode: check GITHUB_TOKEN/GH_TOKEN is set, unexpired, and has read access to the repository (classic PAT with 'repo' scope or fine-grained PAT covering the repo).
- Test the credential manually: git clone https://github.com/${owner}/${repo}.git with the same token to reproduce the denial.
- Confirm app installation includes the specific repository (not just selected repos that exclude it).
Example fix
// before export GITHUB_TOKEN=ghp_expired_token // after: fresh token with repo read access export GITHUB_TOKEN=github_pat_11AAAA..._with_contents_read
Defensive patterns
Strategy: validation
Validate before calling
// Check the token can read the repo before invoking adapter flows
const res = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` },
});
if (!res.ok) throw new Error(`Token cannot read ${owner}/${repo}: HTTP ${res.status}`); Try / catch
try {
await adapter.handleWebhook(payload);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Authentication failed for')) {
// rotate token / verify App installation before retrying
}
} Prevention
- Rotate GITHUB_TOKEN before expiry and grant Contents:Read (classic: repo scope).
- Verify App installation includes each repo and Contents:Read permission.
- Smoke-test the clone with the same credential in CI.
- Prefer App mode so tokens auto-expire/refresh (~1h installation tokens).
When it happens
Trigger: handleWebhook -> ensureRepoReady clones with an installation token or GITHUB_TOKEN/GH_TOKEN that is invalid, expired, or lacks Contents:Read on the target repo.
Common situations: Expired/rotated GITHUB_TOKEN; fine-grained PAT not granted to the repo; GitHub App installed org-wide but without Contents:Read permission; token scoped to a different org; app installed on the org but the repo excluded.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Repository ${owner}/${repo} not found or is private. Check r
- Failed to clone ${owner}/${repo}: ${'message' in cloneResult
- ${data.error}
- Failed to clone repository: ${safeErr.message}
- Copilot authentication failed: ${combined} Run `copilot log
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/5ef6d29f7cb12cf2.
Report an issue: GitHub.