mastra-ai/mastra · error
GitHub installation id is invalid.
Error message
GitHub installation id is invalid.
What it means
Thrown by PlatformGithubIntegration.getRepositoryAccess when the stored installation's externalId is not a positive integer string. The externalId holds GitHub's numeric installation id; if it is missing, empty, or malformed (e.g. 'unknown', '0', whitespace), the code cannot build the token-minting URL and fails fast before calling the Platform API.
Source
Thrown at mastracode/factory/src/integrations/platform/github/integration.ts:397
}),
),
),
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,
});
return access;
} catch (err) {View on GitHub (pinned to 75dd419e61)
Solutions
- Inspect the installation row and set externalId to the numeric GitHub App installation id (digits only, > 0)
- Get the correct id from GitHub (Settings > Applications > Installed GitHub Apps, or the installation webhook payload) and update the row
- Re-sync sources via intake.listSources so the integration rewrites installation rows from the Platform
- Add a pre-insertion validation that externalId matches /^\d+$/
Example fix
// before
await storage.installations.create({ orgId, externalId: 'app-installation-test' });
// after
await storage.installations.create({ orgId, externalId: '12345678' }); // numeric GitHub installation id Defensive patterns
Strategy: validation
Validate before calling
function hasValidExternalId(i: { externalId: string } | undefined): i is { externalId: string } & { externalId: `${number}` } {
return !!i && /^\d+$/.test(i.externalId) && Number(i.externalId) > 0;
} Type guard
function isValidInstallationId(value: string): boolean {
return /^\d+$/.test(value) && Number(value) > 0;
} Prevention
- Validate externalId matches /^\d+$/ before inserting installation rows
- Always write the numeric GitHub installation id from the webhook payload, never a label
- Add a schema constraint or check on the installations.externalId column
- Re-sync installations from the Platform after manual DB edits
When it happens
Trigger: Calling getRepositoryAccess for a repository whose linked installation row has installation.externalId that fails parsePositiveInteger (non-digit characters, empty string, zero-padded/negative value).
Common situations: Manual insertion of the installation row with a placeholder externalId; a sync bug that wrote the account login instead of the numeric GitHub installation id; schema migration left externalId null or empty; importing fixtures with fake ids like 'test-installation'.
Related errors
- GitHub installation id is invalid.
- Version-control installation not found.
- GitHub pull requests require an owner/repository source.
- A review comment requires commitId, path, line, and side unl
- A multi-line review comment requires both startLine and star
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/371156a8e4170dfb.
Report an issue: GitHub.