mastra-ai/mastra · error

Factory session does not belong to this project

Error message

Factory session does not belong to this project

What it means

Thrown by resolveSourceSession as the final ownership check: the session and its project repository exist, but the connection backing that repository is missing or its factoryProjectId does not match request.factoryProjectId. The library refuses to start a session against a factory project it is not actually bound to, preventing cross-project access.

Source

Thrown at mastracode/factory/src/rules/start-coordinator.ts:98

  return `<skill name="${skill.name}">\n${escapeSkillBoundary(content)}\n</skill>`;
}

async function resolveSourceSession(
  storage: SourceControlStorageHandle,
  request: FactoryStartRequest,
): Promise<SourceControlSession> {
  const session = await storage.sessions.getBySessionId(request.sessionId);
  if (!session || session.orgId !== request.orgId || session.userId !== request.userId) {
    throw new Error('Factory session not found');
  }
  const projectRepository = await storage.projectRepositories.get({
    orgId: request.orgId,
    id: session.projectRepositoryId,
  });
  if (!projectRepository) throw new Error('Factory session repository not found');
  const connection = await storage.connections.get({ orgId: request.orgId, id: projectRepository.connectionId });
  if (!connection || connection.factoryProjectId !== request.factoryProjectId) {
    throw new Error('Factory session does not belong to this project');
  }
  return session;
}

async function configureThread(session: FactorySession, request: FactoryStartRequest): Promise<string> {
  const threadId = session.thread.requireId();
  await session.thread.rename({ title: request.threadTitle });
  const settings = { ...(request.threadTags ?? {}), factorySessionId: request.sessionId };
  await Promise.all(Object.entries(settings).map(([key, value]) => session.thread.setSetting({ key, value })));
  return threadId;
}

export class FactoryStartCoordinator {
  readonly #controller: FactoryController;
  readonly #storage: WorkItemsStorage;
  readonly #transitionService?: Pick<FactoryTransitionService, 'transition'>;
  readonly #sourceControl?: SourceControlStorageHandle;
  readonly #memorySettings?: MemorySettingsStorage;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass the correct factoryProjectId — the one on the connection that owns the session's repository (storage.connections.get({orgId, id: repo.connectionId}).factoryProjectId).
  2. If the connection is missing, reconnect the repository (recreate the connection) so projectRepository.connectionId resolves.
  3. If the project was recreated with a new ID, re-bind the repository's connection to the new factoryProjectId or create a new session under the new project.
  4. Verify no environment/config mismatch: the request's factoryProjectId should come from the same environment as the storage data.

Example fix

// before: wrong project in request
await factory.prepare({ sessionId, orgId, userId, factoryProjectId: 'proj_default' });

// after: resolve the project from the session's repo connection
const session = await storage.sessions.getBySessionId(sessionId);
const repo = await storage.projectRepositories.get({ orgId, id: session.projectRepositoryId });
const conn = await storage.connections.get({ orgId, id: repo.connectionId });
await factory.prepare({ sessionId, orgId, userId, factoryProjectId: conn.factoryProjectId });
Defensive patterns

Strategy: validation

Validate before calling

const session = await storage.sessions.getBySessionId(request.sessionId);
const repo = session && await storage.projectRepositories.get({ orgId: request.orgId, id: session.projectRepositoryId });
const conn = repo && await storage.connections.get({ orgId: request.orgId, id: repo.connectionId });
if (!conn) throw new Error('Repository connection is missing; reconnect the repository.');
if (conn.factoryProjectId !== request.factoryProjectId) {
  throw new Error(`Expected factoryProjectId ${conn.factoryProjectId}, got ${request.factoryProjectId}.`);
}

Type guard

function matchesProject(conn: Connection | undefined, req: FactoryStartRequest): conn is Connection {
  return !!conn && conn.factoryProjectId === req.factoryProjectId;
}

Try / catch

try {
  const prepared = await coordinator.prepare(request);
} catch (err) {
  if (err instanceof Error && err.message === 'Factory session does not belong to this project') {
    console.error('factoryProjectId in the request does not match the session’s repository connection; resolve it from the connection.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling factory start with a factoryProjectId that differs from the one on the repository's connection (wrong project passed in the request), the repository's connection was deleted (connection lookup returns undefined), or the repo was re-pointed to a different factory project after the session was created.

Common situations: Automation passing a hardcoded/default factoryProjectId while the session lives under another project; a project was deleted and recreated (new factoryProjectId) but old connections/sessions still point at the old ID; moving a repo between factory projects without updating sessions.

Related errors


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