{"record":{"id":"0a7c04736af11482","repo":"mastra-ai/mastra","slug":"repository-does-not-belong-to-the-connection-insta","errorCode":null,"errorMessage":"Repository does not belong to the connection installation.","messagePattern":"Repository does not belong to the connection installation\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/storage/domains/source-control/base.ts","lineNumber":853,"sourceCode":"                id: connection.factory_project_id,\n                org_id: installation.org_id,\n              });\n              if (!project) continue;\n              targets.push({\n                orgId: installation.org_id,\n                factoryProjectId: connection.factory_project_id,\n                projectRepository: toProjectRepository(link),\n              });\n            }\n          }\n          return targets;\n        },\n        get: getProjectRepository,\n        link: async input => {\n          const connection = await requireConnection({ orgId: input.orgId, id: input.connectionId });\n          const repository = await requireRepository({ orgId: input.orgId, id: input.repositoryId });\n          if (repository.installationId !== connection.installationId) {\n            throw new Error('Repository does not belong to the connection installation.');\n          }\n          const now = new Date();\n          try {\n            const row = await db().insertOne<ProjectRepositoryDbRow>(PROJECT_REPOSITORIES, {\n              connection_id: input.connectionId,\n              repository_id: input.repositoryId,\n              created_by_user_id: input.createdByUserId,\n              branch: input.branch ?? null,\n              sandbox_provider: input.sandboxProvider,\n              sandbox_workdir: input.sandboxWorkdir,\n              setup_command: input.setupCommand ?? null,\n              teardown_command: input.teardownCommand ?? null,\n              created_at: now,\n              updated_at: now,\n            });\n            return toProjectRepository(row);\n          } catch (error) {\n            // Match the in-memory handle: return the existing row unchanged on","sourceCodeStart":835,"sourceCodeEnd":871,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/storage/domains/source-control/base.ts#L835-L871","documentation":"Thrown by projectRepositories.link when the repository's installationId differs from the connection's installationId. A project repository link is only valid when both the connection and the repository are attached to the same source-control installation.","triggerScenarios":"Linking a repository created under installation A to a connection created under installation B (e.g., after reinstalling the GitHub App or migrating only one side).","commonSituations":"GitHub App reinstall created a new installation ID; migrateInstallation moved a repo but the connection still points at the old installation; mixing repos across orgs/apps.","solutions":["Re-link after migrating the connection to the same installation (connections migrate or recreate)","Call migrateInstallation on the repository to move it to the connection's installationId","Recreate the connection under the repository's installation","Verify installationIds match before linking"],"exampleFix":"// before\nawait forIntegration.projectRepositories.link({ orgId, connectionId, repositoryId });\n// after\nconst conn = await forIntegration.connections.get({ orgId, id: connectionId });\nconst repo = await forIntegration.repositories.get({ orgId, id: repositoryId });\nif (repo.installationId !== conn.installationId) {\n  await api.migrateInstallation({ orgId, id: repositoryId, newInstallationId: conn.installationId });\n}\nawait forIntegration.projectRepositories.link({ orgId, connectionId, repositoryId });","handlingStrategy":"validation","validationCode":"const conn = await getConnection({ orgId, id: connectionId });\nconst repo = await getRepository({ orgId, id: repositoryId });\nif (!conn || !repo) throw new Error('connection/repository missing');\nif (repo.installationId !== conn.installationId) throw new Error('Installation mismatch before link');","typeGuard":"function sameInstallation(\n  c: { installationId: string },\n  r: { installationId: string }\n): boolean {\n  return c.installationId === r.installationId;\n}","tryCatchPattern":"try {\n  await link({ orgId, connectionId, repositoryId });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('does not belong to the connection installation')) {\n    await migrateInstallation({ orgId, id: repositoryId, newInstallationId: conn.installationId });\n    await link({ orgId, connectionId, repositoryId });\n  } else throw e;\n}","preventionTips":["After a GitHub App reinstall, migrate both repos and connections to the new installation","Assert installationId equality before linking","Avoid mixing installations across apps/orgs"],"tags":["source-control","installation-mismatch","repository","link"],"backgroundTag":"installation-mismatch","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}