mastra-ai/mastra · error

Version-control repository not found.

Error message

Version-control repository not found.

What it means

Thrown by PlatformGithubIntegration (integration.ts:392) during repository access resolution when storage.repositories.get({orgId, repositoryId}) returns no record for the given org/repository pair. The integration needs the stored repository row (slug, installationId) to build the clone URL and locate the GitHub App installation, so a missing row is unrecoverable for that request.

Source

Thrown at mastracode/factory/src/integrations/platform/github/integration.ts:392

              externalId: repository.externalId,
              slug: repository.slug,
              defaultBranch: repository.defaultBranch,
              providerMetadata: repository.metadata,
            },
          }),
        ),
      ),
    getRepositoryAccess: async ({ orgId, repositoryId }) => {
      // Every session materialization requests access; reuse a recent grant
      // instead of re-minting through the Platform each time. The TTL keeps
      // a wide margin under GitHub's ~60min installation-token lifetime.
      const cacheKey = `${orgId}:${repositoryId}`;
      const cached = this.#repositoryAccessCache.get(cacheKey);
      if (cached && cached.expiresAt > Date.now()) return cached.access;
      this.#repositoryAccessCache.delete(cacheKey);

      const repository = await this.storage.repositories.get({ orgId, id: repositoryId });
      if (!repository) throw new Error('Version-control repository not found.');
      const cloneUrl = `https://github.com/${repository.slug}.git`;
      const installation = await this.storage.installations.get({ orgId, id: repository.installationId });
      if (!installation) throw new Error('Version-control installation not found.');
      const installationId = parsePositiveInteger(installation.externalId);
      if (installationId === null) throw new Error('GitHub installation id is invalid.');
      const repositoryName = splitRepository(repository.slug).repo;

      try {
        const token = await this.#client.request<{ token: string }>(
          'POST',
          `${API_PREFIX}/github-app/installations/${installationId}/token`,
          { repositories: [repositoryName], permissions: REPOSITORY_TOKEN_PERMISSIONS },
        );
        const access: RepositoryAccess = {
          cloneUrl,
          authorization: { scheme: 'bearer', token: token.token },
        };
        setBounded(this.#repositoryAccessCache, cacheKey, {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the repositoryId exists in storage for that orgId (storage.repositories.get({orgId, id})) before invoking the integration.
  2. Check that the orgId matches the org the repository was registered under — cross-org IDs always miss.
  3. Re-register/sync the repository (re-run the installation sync) if the row was deleted or the storage was reset.
  4. Purge stale references: drop events/webhooks for deleted repositories instead of retrying them.
  5. Catch this error and skip/mark the repository as unavailable rather than crashing a batch reconciliation.

Example fix

// before
const access = await integration.resolveRepositoryAccess({ orgId, repositoryId }); // throws if deleted

// after
const repo = await storage.repositories.get({ orgId, id: repositoryId });
if (!repo) {
  logger.warn('Repository no longer exists; skipping', { orgId, repositoryId });
  return null;
}
const access = await integration.resolveRepositoryAccess({ orgId, repositoryId });
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the repository exists before requesting access through the integration
const repo = await storage.repositories.get({ orgId, id: repositoryId });
if (!repo) {
  throw new skipSignal(`Repository ${repositoryId} not found for org ${orgId}; skipping`);
}

Type guard

function isRepositoryRecord(v: unknown): v is { id: string; slug: string; installationId: string } {
  return (
    typeof v === 'object' && v !== null &&
    'id' in v && 'slug' in v && 'installationId' in v &&
    typeof (v as any).slug === 'string'
  );
}

Try / catch

try {
  const access = await integration.resolveRepositoryAccess({ orgId, repositoryId });
} catch (err) {
  if (err instanceof Error && err.message === 'Version-control repository not found.') {
    logger.warn('Repository deleted or wrong org; skipping', { orgId, repositoryId });
    return null; // do not retry: the row will not reappear on its own
  }
  throw err;
}

Prevention

When it happens

Trigger: Requesting repository-scoped operations with a repositoryId that was never registered, belongs to a different orgId, or whose row was deleted from storage; stale references held after a repository was removed from the platform; cache misses force re-reads, exposing deletions that cached entries previously hid.

Common situations: Replaying an old webhook/event referencing a since-deleted repository; tenant/org mixups where the repository exists under another orgId; database resets or migrations dropping repository rows; typos or stale IDs in configuration calling the integration directly.

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/255f869ac38ff486. Report an issue: GitHub.