mastra-ai/mastra · error

Repository link ${session.projectRepositoryId} was not found

Error message

Repository link ${session.projectRepositoryId} was not found

What it means

A Factory session references a project-repository link (projectRepositoryId). If storage.projectRepositories.get returns nothing for that id in the session's org, createWorkspaceFactory throws because it cannot determine which repository the workspace should be built around.

Source

Thrown at mastracode/factory/src/workspace.ts:288

    if (!user?.organizationId || !userId) {
      throw new Error(`Factory session ${session.sessionId} was resolved without a caller identity`);
    }
    // Org-visible sessions open to any member of the owning organization;
    // only private sessions stay owner-only. Cross-org access never passes.
    if (user.organizationId !== session.orgId || (session.visibility === 'private' && userId !== session.userId)) {
      throw new Error(`Factory session ${session.sessionId} is not available to the current user`);
    }
    if (!sandboxConfig || !github) {
      throw new Error('GitHub and a sandbox callback are required to create a Factory session workspace');
    }
    const createSessionSandboxInstance = sandboxConfig;

    const storage = github.sourceControlStorage;
    const projectRepository = await storage.projectRepositories.get({
      orgId: session.orgId,
      id: session.projectRepositoryId,
    });
    if (!projectRepository) throw new Error(`Repository link ${session.projectRepositoryId} was not found`);
    // The remaining reads only depend on the repository link — issue them in
    // parallel instead of paying four sequential storage round-trips.
    const [connection, repository] = await Promise.all([
      storage.connections.get({ orgId: session.orgId, id: projectRepository.connectionId }),
      storage.repositories.get({ orgId: session.orgId, id: projectRepository.repositoryId }),
    ]);
    if (!connection || !repository) throw new Error(`Repository link ${session.projectRepositoryId} is incomplete`);
    const installation = await storage.installations.get({ orgId: session.orgId, id: connection.installationId });
    if (!installation) throw new Error(`GitHub installation ${connection.installationId} was not found`);
    const repoFullName = repository.slug;

    // Construct (or fetch) the session's memoized sandbox instance.
    // Construction is cheap and side-effect-free by the callback contract —
    // the VM is provisioned on `start()`, which only the materialization
    // pipeline calls. The workdir is never persisted or trusted from storage
    // or client input (the stale-workdir incident class came from reusing
    // `session.sandboxWorkdir` written under a different provider): local
    // sandboxes derive it at construction, remote sandboxes clone into the

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Recreate the repository link (projectRepositories.create) and update the session's projectRepositoryId
  2. Confirm the link exists in the same org: storage.projectRepositories.get({ orgId: session.orgId, id: session.projectRepositoryId })
  3. Delete and recreate the session against a valid repository link if the old link is unrecoverable

Example fix

// before
const factory = await createWorkspaceFactory({ session }); // link deleted
// after
const link = await storage.projectRepositories.get({ orgId: session.orgId, id: session.projectRepositoryId });
if (!link) {
  const newLink = await storage.projectRepositories.create({ orgId: session.orgId, connectionId, repositoryId });
  await storage.sessions.update({ id: session.id, projectRepositoryId: newLink.id });
}
const factory = await createWorkspaceFactory({ session });
Defensive patterns

Strategy: validation

Validate before calling

const link = await storage.projectRepositories.get({ orgId: session.orgId, id: session.projectRepositoryId });
if (!link) throw new Error(`Repository link ${session.projectRepositoryId} missing; recreate it before resolving the session`);

Type guard

null

Try / catch

try {
  factory = await createWorkspaceFactory({ session, user });
} catch (e) {
  if (e.message.includes('Repository link') && e.message.includes('was not found')) {
    // recreate link + update session, then retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Resolving a session whose projectRepositoryId points to a deleted project-repository link, an id from another org, or a session created against storage that has since been cleared/migrated.

Common situations: Repository link deleted by an admin while a session still references it, restoring sessions from a backup without the linked projectRepositories rows, or cross-environment storage mismatch.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/6a06f5ca6f8112ba. Report an issue: GitHub.