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
- Pass the correct factoryProjectId — the one on the connection that owns the session's repository (storage.connections.get({orgId, id: repo.connectionId}).factoryProjectId).
- If the connection is missing, reconnect the repository (recreate the connection) so projectRepository.connectionId resolves.
- 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.
- 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
- Always derive factoryProjectId from the session’s repository connection rather than hardcoding it.
- When recreating a deleted project, re-bind connections and open new sessions for the new project ID.
- Log orgId/projectId/sessionId together in automation to spot cross-project mismatches early.
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
- Thread not found: ${threadId}
- Version with id ${versionId} not found for MCP client ${mcpC
- Google user is not in an allowed hosted domain
- OAuth failed: ${tokenData.error}
- Pull request repository does not match the active project re
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e2b04c7bec097e75.
Report an issue: GitHub.