paperclipai/paperclip · error

GitHub inventory failed: install this GitHub App on the sele

Error message

GitHub inventory failed: install this GitHub App on the selected repositories first

What it means

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.

Source

Thrown at server/src/services/chat-provider-inventory.ts:298

      },
    );
    const pageInstallations = await jsonResponse<
      Array<{
        id?: number;
        account?: { id?: number; login?: string; name?: string; type?: string };
        permissions?: Record<string, string>;
        suspended_at?: string | null;
      }>
    >(response, "GitHub");
    installations.push(...pageInstallations);
    if (pageInstallations.length < 100) break;
  }
  const active = installations.filter(
    (installation) =>
      Number.isFinite(installation.id) && !installation.suspended_at,
  );
  if (active.length === 0) {
    throw new Error(
      "GitHub inventory failed: install this GitHub App on the selected repositories first",
    );
  }
  if (active.length !== 1) {
    throw new Error(
      "GitHub inventory failed: this chat connection requires a dedicated GitHub App with exactly one active installation",
    );
  }
  const installation = active[0]!;
  const missingPermissions = Object.entries(
    REQUIRED_GITHUB_INSTALLATION_PERMISSIONS,
  )
    .filter(
      ([permission, access]) =>
        installation.permissions?.[permission] !== access,
    )
    .map(([permission]) => permission);
  if (missingPermissions.length > 0) {

View on GitHub (pinned to 01ad858492)

Solutions

  1. Install the GitHub App on the target repositories at its installation URL (github.com/apps/<app-name>/installations/new).
  2. If suspended, reactivate the installation via org settings or resolve the suspension reason with GitHub.
  3. Verify you are configuring the correct GitHub App (one that actually has installations).
  4. Re-run discovery after installation completes.
Defensive patterns

Strategy: validation

Validate before calling

// Check installation status before running discovery:
const installs = await gh.request('GET /app/installations');
const active = installs.data.filter(i => !i.suspended_at);
if (active.length === 0) {
  throw new Error('Install the GitHub App on the target repositories first: https://github.com/apps/<app>/installations/new');
}

Type guard

function hasActiveInstallation(list: { id: number; suspended_at?: string | null }[]): boolean {
  return list.some(i => Number.isFinite(i.id) && !i.suspended_at);
}

Try / catch

try { await discoverDedicatedGitHubAppInstallation(input); }
catch (e) {
  if (e.message.includes('install this GitHub App')) {
    // surface the App installation URL to the user, then re-run discovery
    await showInstallPrompt(appSlug);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/fc47e397063a60c2. Report an issue: GitHub.