{"record":{"id":"36ca0b6a661f0d1d","repo":"coleam00/Archon","slug":"authentication-failed-for-owner-repo-check","errorCode":null,"errorMessage":"Authentication failed for ${owner}/${repo}. Check GITEA_TOKEN permissions.","messagePattern":"Authentication failed for (.+?)/(.+?)\\. Check GITEA_TOKEN permissions\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapters/src/community/forge/gitea/adapter.ts","lineNumber":553,"sourceCode":"\n    // Parse URL to get host for authenticated clone\n    const urlObj = new URL(this.baseUrl);\n    const repoUrl = `${urlObj.protocol}//${urlObj.host}/${owner}/${repo}.git`;\n\n    const cloneResult = await cloneRepository(repoUrl, toRepoPath(repoPath), {\n      token: process.env.GITEA_TOKEN,\n    });\n\n    if (!cloneResult.ok) {\n      getLog().error({ owner, repo, repoPath, error: cloneResult.error }, 'repo_clone_failed');\n\n      if (cloneResult.error.code === 'not_a_repo') {\n        throw new Error(\n          `Repository ${owner}/${repo} not found or is private. Check repository access.`\n        );\n      }\n      if (cloneResult.error.code === 'permission_denied') {\n        throw new Error(\n          `Authentication failed for ${owner}/${repo}. Check GITEA_TOKEN permissions.`\n        );\n      }\n      const unknownMsg = (cloneResult.error as { message?: string }).message ?? 'unknown error';\n      throw new Error(`Failed to clone ${owner}/${repo}: ${unknownMsg}`);\n    }\n\n    await addSafeDirectory(toRepoPath(repoPath));\n  }\n\n  /**\n   * Auto-detect and load commands from .archon/commands/ (or configured folder)\n   */\n  private async autoDetectAndLoadCommands(repoPath: string, codebaseId: string): Promise<void> {\n    const commandFolders = getCommandFolderSearchPaths();\n\n    for (const folder of commandFolders) {\n      try {","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/adapters/src/community/forge/gitea/adapter.ts#L535-L571","documentation":"When the clone operation reports error code 'permission_denied', ensureRepoReady throws this message indicating the GITEA_TOKEN failed authentication or lacks permission for owner/repo. It is distinguished from 'not_a_repo' so operators know the repository exists but the credentials were rejected.","triggerScenarios":"handleWebhook -> ensureRepoReady cloning with a token that is expired, revoked, wrong for the instance, or scoped to a user without read access; token present but sent with a malformed Authorization header by the git credential helper.","commonSituations":"Gitea token regenerated without updating the adapter's env; token created without any scope; deploying the adapter with a token from a different Gitea instance; LDAP/SSO user disabled so the token is invalidated.","solutions":["Regenerate GITEA_TOKEN in Gitea with repo read scope and update the adapter's environment.","Test the token directly: curl -H \"Authorization: token $GITEA_TOKEN\" <gitea>/api/v1/user.","Confirm the token belongs to an account with read access to owner/repo on the correct instance.","Check that the token is actually reaching git (credential helper / remote URL embeds the token)."],"exampleFix":"// before\nclone of https://gitea.example.com/owner/repo.git -> permission_denied (token scopes: read:user)\n\n// after\n# regenerate token with \"repository\" read scope\nGITEA_TOKEN=<token with repository:read>","handlingStrategy":"validation","validationCode":"const res = await fetch(`${giteaUrl}/api/v1/user`, { headers: { Authorization: `token ${token}` } });\nif (res.status === 401) throw new Error('GITEA_TOKEN rejected: regenerate with repository read scope');","typeGuard":null,"tryCatchPattern":"try {\n  await adapter.handleWebhook(update);\n} catch (err) {\n  if (String(err).startsWith('Authentication failed for')) {\n    alertOperator('GITEA_TOKEN invalid or under-scoped for ' + extractRepo(String(err)));\n  }\n  throw err;\n}","preventionTips":["Validate the token against GET /api/v1/user during deployment health checks.","Rotate tokens before expiry and update the secret store atomically.","Grant the token's account explicit read access to the repository.","Confirm the token belongs to the same Gitea instance the adapter is configured for."],"tags":["gitea","auth","token"],"backgroundTag":"git-authentication-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}