mastra-ai/mastra · error

Source-control installation not found for this organization

Error message

Source-control installation not found for this organization and integration.

What it means

requireInstallation loads a source-control installation by orgId and id via getInstallation and throws a plain Error ('Source-control installation not found...') when no row matches. forIntegration depends on it, so any read of repositories/config under an installation first asserts the installation exists for that org.

Source

Thrown at mastracode/factory/src/storage/domains/source-control/base.ts:560

  }

  forIntegration(integrationId: string): SourceControlStorageHandle {
    if (!integrationId.trim()) throw new Error('[SourceControlStorage] integrationId must not be empty.');
    const db = (): FactoryStorageOps => this.ops;

    const getInstallation = async (args: { orgId: string; id: string }): Promise<SourceControlInstallation | null> => {
      const row = await db().findOne<InstallationDbRow>(INSTALLATIONS, {
        id: args.id,
        integration_id: integrationId,
        org_id: args.orgId,
      });
      return row ? toInstallation(row) : null;
    };

    const requireInstallation = async (args: { orgId: string; id: string }): Promise<SourceControlInstallation> => {
      const installation = await getInstallation(args);
      if (!installation)
        throw new Error('Source-control installation not found for this organization and integration.');
      return installation;
    };

    const getRepository = async (args: { orgId: string; id: string }): Promise<SourceControlRepository | null> => {
      const row = await db().findOne<RepositoryDbRow>(REPOSITORIES, { id: args.id });
      if (!row || !(await getInstallation({ orgId: args.orgId, id: row.installation_id }))) return null;
      return toRepository(row);
    };

    const requireRepository = async (args: { orgId: string; id: string }): Promise<SourceControlRepository> => {
      const repository = await getRepository(args);
      if (!repository) throw new Error('Source-control repository not found for this organization and integration.');
      return repository;
    };

    const getConnection = async (args: {
      orgId: string;
      id: string;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the installation id is correct and still exists for the given orgId
  2. Re-authorize/reinstall the source-control app to recreate the installation if it was revoked
  3. List installations for the org to get the current valid id
  4. Ensure the orgId used matches the installation's organization

Example fix

// before
await sourceControl.forIntegration({ orgId, id: staleInstallationId });
// after
const existing = await sourceControl.getInstallation?.({ orgId, id: staleInstallationId });
if (!existing) throw new Error('Reinstall the source-control app to recreate the installation');
await sourceControl.forIntegration({ orgId, id: staleInstallationId });
Defensive patterns

Strategy: try-catch

Validate before calling

const installation = await sourceControl.getInstallation?.({ orgId, id });
if (!installation) throw new Error(`Installation ${id} not found for org ${orgId}; reinstall the source-control app.`);

Type guard

function hasInstallation<T extends SourceControlInstallation | null>(x: T): x is Exclude<T, null> {
  return x !== null;
}

Try / catch

try {
  const integration = await sourceControl.forIntegration({ orgId, id });
} catch (e) {
  if (e instanceof Error && e.message.includes('installation not found')) {
    // trigger re-auth / app reinstall flow for the org
    await promptSourceControlReconnect(orgId);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling forIntegration (or another method that routes through requireInstallation) with an installation id that doesn't exist, or an installation belonging to a different orgId than the one passed.

Common situations: Using an installation ID from a deleted/uninstalled GitHub app; hardcoding an ID from another environment; orgId mismatch after tenant/organization switch; DB wipe or migration leaving orphaned repository rows.

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 mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/2cf9b132821a115d. Report an issue: GitHub.