mastra-ai/mastra · error
GitHub installation id is invalid.
Error message
GitHub installation id is invalid.
What it means
Thrown when the stored installation's externalId cannot be parsed into a safe integer. The integration parses externalId with Number.parseInt and requires Number.isSafeInteger before minting an installation token, so a malformed or non-numeric external id aborts credential resolution.
Source
Thrown at mastracode/factory/src/integrations/github/integration.ts:300
installationId,
externalId: repository.externalId,
slug: repository.slug,
defaultBranch: repository.defaultBranch,
providerMetadata: repository.metadata,
},
}),
),
),
getRepositoryAccess: async ({ orgId, repositoryId }) => {
const repository = await this.sourceControlStorage.repositories.get({ orgId, id: repositoryId });
if (!repository) throw new Error('Version-control repository not found.');
const installation = await this.sourceControlStorage.installations.get({
orgId,
id: repository.installationId,
});
if (!installation) throw new Error('Version-control installation not found.');
const installationId = Number.parseInt(installation.externalId, 10);
if (!Number.isSafeInteger(installationId)) throw new Error('GitHub installation id is invalid.');
return {
cloneUrl: `https://github.com/${repository.slug}.git`,
authorization: { scheme: 'bearer', token: await this.mintInstallationToken(installationId) },
};
},
listPullRequests: input => this.#listPullRequests(input),
getPullRequest: input => this.#getPullRequest(input),
createPullRequest: input => this.#createPullRequest(input),
updatePullRequest: input => this.#updatePullRequest(input),
closePullRequest: input => this.#closePullRequest(input),
mergePullRequest: input => this.#mergePullRequest(input),
listComments: input => this.#listComments(input),
createComment: input => this.#createComment(input),
updateComment: input => this.#updateComment(input),
deleteComment: input => this.#deleteComment(input),
listReviews: input => this.#listReviews(input),
getReview: input => this.#getReview(input),
createReview: input => this.#createReview(input),View on GitHub (pinned to 75dd419e61)
Solutions
- Fix the installation record so externalId holds the numeric GitHub App installation id as a decimal string
- Re-sync the installation from GitHub so externalId is populated correctly
- Validate externalId with Number.isSafeInteger(Number.parseInt(externalId, 10)) at write time to reject bad values early
Example fix
// before
await installations.upsert({ orgId, externalId: 'ghapp-abc123' });
// after
await installations.upsert({ orgId, externalId: '51982311' }); // numeric GitHub installation id Defensive patterns
Strategy: validation
Validate before calling
if (!/^[0-9]+$/.test(installation.externalId ?? '') || !Number.isSafeInteger(Number(installation.externalId))) {
throw new Error('installation externalId must be a numeric GitHub installation id');
} Type guard
function hasNumericInstallationId(inst: { externalId: string | null }): boolean {
const n = Number.parseInt(inst.externalId ?? '', 10);
return Number.isSafeInteger(n);
} Try / catch
try {
const creds = await gh.getCloneCredentials({ orgId, repositoryId });
} catch (e) {
if (e.message === 'GitHub installation id is invalid.') {
// re-sync the installation record from GitHub
} else throw e;
} Prevention
- Validate externalId format at upsert time, rejecting non-numeric values
- Store GitHub installation ids as strings of digits exactly as returned by the API
- Add a data-integrity check that parses all stored externalIds on migration
When it happens
Trigger: Resolving clone credentials for a repository whose installation record has an externalId that is empty, non-numeric (e.g. a UUID or slug), or exceeds Number.MAX_SAFE_INTEGER.
Common situations: A different integration/adapter stored its own identifier format in externalId; a migration wrote the GitHub installation id as a string with whitespace or a non-numeric placeholder; extremely large ids stored with formatting.
Related errors
- GitHub installation id is invalid.
- 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
- GitHub triage comments require an owner/repository source.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/7b3eca23d03db03c.
Report an issue: GitHub.