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
- Verify the repositoryId exists in storage for that orgId (storage.repositories.get({orgId, id})) before invoking the integration.
- Check that the orgId matches the org the repository was registered under — cross-org IDs always miss.
- Re-register/sync the repository (re-run the installation sync) if the row was deleted or the storage was reset.
- Purge stale references: drop events/webhooks for deleted repositories instead of retrying them.
- 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
- Resolve repository IDs from current storage, not cached webhook payloads from deleted repos.
- Confirm orgId scoping when operating multi-tenant — always pair orgId + repositoryId from the same source record.
- After storage resets/migrations, re-sync installations before running repository operations.
- Mark missing repositories permanently skipped instead of retrying in loops.
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
- Version-control repository not found.
- Project repository not found for this organization.
- Source-control connection not found for this organization.
- Repository not found for this organization.
- Source-control installation not found for this organization.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/255f869ac38ff486.
Report an issue: GitHub.