mastra-ai/mastra · error
Version-control installation not found.
Error message
Version-control installation not found.
What it means
Thrown by PlatformGithubIntegration.getRepositoryAccess when the local installation record referenced by repository.installationId cannot be found in storage. The library stores repositories and their owning GitHub App installations as separate rows; a repository row pointing at a missing installation row means stale or inconsistent linkage data, so no installation token can be minted.
Source
Thrown at mastracode/factory/src/integrations/platform/github/integration.ts:395
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, {
access,
expiresAt: Date.now() + REPOSITORY_ACCESS_CACHE_TTL_MS,
});View on GitHub (pinned to 75dd419e61)
Solutions
- Re-run the integration's source sync (intake.listSources) so the repository row is relinked to the current installation row
- Check storage for the installation row: verify an installation exists with id === repository.installationId in the same org
- If the app was reinstalled, update repository.installationId to the new installation's id
- Restore the deleted installation row from backup or recreate it via the app-installation webhook
Example fix
// before (stale reference)
await storage.repositories.update({ orgId, id: repositoryId, installationId: OLD_INSTALLATION_ID });
// after (relink to reinstalled app installation)
const installation = await storage.installations.getByExternalId({ orgId, externalId: newGithubInstallationId });
await storage.repositories.update({ orgId, id: repositoryId, installationId: installation.id }); Defensive patterns
Strategy: try-catch
Validate before calling
const repo = await storage.repositories.get({ orgId, id: repositoryId });
if (!repo) throw new Error('repository not found');
const installation = await storage.installations.get({ orgId, id: repo.installationId });
if (!installation) throw new Error(`installation ${repo.installationId} missing for repository ${repositoryId}`); Try / catch
try {
const access = await github.getRepositoryAccess({ orgId, repositoryId });
} catch (err) {
if (err instanceof Error && err.message === 'Version-control installation not found.') {
await resyncSources(orgId); // relink repository to current installation
} else throw err;
} Prevention
- Re-sync sources after any GitHub App uninstall/reinstall
- Use cascading deletes or referential checks so repository rows never outlive their installation row
- Monitor for orphaned repository rows with a periodic integrity query
- Persist the GitHub installation external id so rows can be re-linked deterministically
When it happens
Trigger: Calling getRepositoryAccess (directly or via session materialization) for a repository whose installationId does not resolve to an installation row in this.storage.installations.get({ orgId, id }).
Common situations: The GitHub App was uninstalled and the installation row was deleted (or a reinstall created a new installation row) while the repository row still references the old installation id; manual DB cleanup or a partial sync removed the installation; cross-org id mismatch.
Related errors
- Source-control installation not found for this organization.
- GitHub installation id is invalid.
- Version-control repository not found.
- Version-control installation not found.
- GitHub installation id is invalid.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/c236e0406c22aed0.
Report an issue: GitHub.