{"record":{"id":"fc47e397063a60c2","repo":"paperclipai/paperclip","slug":"github-inventory-failed-install-this-github-app-o","errorCode":null,"errorMessage":"GitHub inventory failed: install this GitHub App on the selected repositories first","messagePattern":"GitHub inventory failed: install this GitHub App on the selected repositories first","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/chat-provider-inventory.ts","lineNumber":298,"sourceCode":"      },\n    );\n    const pageInstallations = await jsonResponse<\n      Array<{\n        id?: number;\n        account?: { id?: number; login?: string; name?: string; type?: string };\n        permissions?: Record<string, string>;\n        suspended_at?: string | null;\n      }>\n    >(response, \"GitHub\");\n    installations.push(...pageInstallations);\n    if (pageInstallations.length < 100) break;\n  }\n  const active = installations.filter(\n    (installation) =>\n      Number.isFinite(installation.id) && !installation.suspended_at,\n  );\n  if (active.length === 0) {\n    throw new Error(\n      \"GitHub inventory failed: install this GitHub App on the selected repositories first\",\n    );\n  }\n  if (active.length !== 1) {\n    throw new Error(\n      \"GitHub inventory failed: this chat connection requires a dedicated GitHub App with exactly one active installation\",\n    );\n  }\n  const installation = active[0]!;\n  const missingPermissions = Object.entries(\n    REQUIRED_GITHUB_INSTALLATION_PERMISSIONS,\n  )\n    .filter(\n      ([permission, access]) =>\n        installation.permissions?.[permission] !== access,\n    )\n    .map(([permission]) => permission);\n  if (missingPermissions.length > 0) {","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-provider-inventory.ts#L280-L316","documentation":"Thrown by discoverDedicatedGitHubAppInstallation when, after listing the App's installations, zero installations are active (finite id and no suspended_at). This connection type requires exactly one active GitHub App installation; none found means the App has never been installed, was uninstalled, or its only installation is suspended.","triggerScenarios":"installations.filter(...) yields length 0: the GitHub App has no installations, the only installation was uninstalled by an org owner, or the sole installation is suspended.","commonSituations":"Admin installed the App org-wide then uninstalled it; GitHub suspended the installation for billing/policy reasons; connecting to the wrong App (one with zero installs); choosing 'selected repositories' mode when the App was never granted any repos.","solutions":["Install the GitHub App on the target repositories at its installation URL (github.com/apps/<app-name>/installations/new).","If suspended, reactivate the installation via org settings or resolve the suspension reason with GitHub.","Verify you are configuring the correct GitHub App (one that actually has installations).","Re-run discovery after installation completes."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check installation status before running discovery:\nconst installs = await gh.request('GET /app/installations');\nconst active = installs.data.filter(i => !i.suspended_at);\nif (active.length === 0) {\n  throw new Error('Install the GitHub App on the target repositories first: https://github.com/apps/<app>/installations/new');\n}","typeGuard":"function hasActiveInstallation(list: { id: number; suspended_at?: string | null }[]): boolean {\n  return list.some(i => Number.isFinite(i.id) && !i.suspended_at);\n}","tryCatchPattern":"try { await discoverDedicatedGitHubAppInstallation(input); }\ncatch (e) {\n  if (e.message.includes('install this GitHub App')) {\n    // surface the App installation URL to the user, then re-run discovery\n    await showInstallPrompt(appSlug);\n  }\n}","preventionTips":["Install the App on the intended repositories before connecting in Paperclip.","Monitor installation suspension emails from GitHub and resolve promptly.","Use org-wide installs where policy permits to reduce uninstalled-by-accident risk.","Re-run discovery immediately after installing to confirm exactly one active installation."],"tags":["github","app-installation","setup","inventory"],"backgroundTag":"resource-not-found","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}