mastra-ai/mastra · error
Session is not available to the current user
Error message
Session is not available to the current user
What it means
resolveAuthorizedSession maps a workspacePath that is a Factory session id to a session record. When auth is enabled, after confirming the session exists it compares the caller's tenant (orgId/userId from deps.auth) with the session owner and throws 'Session is not available to the current user' on mismatch. This is a tenancy/ownership guard: a session exists but belongs to a different user or organization, so it must not be visible to the caller (distinct from returning null, which means no such session at all).
Source
Thrown at mastracode/factory/src/routes/fs.ts:449
/**
* Resolve a `workspacePath` query param as a Factory session id. Returns the
* session when one exists and the caller owns it, `null` when no session
* matches (the caller should fall back to local-path handling), and throws
* when a session exists but belongs to another tenant.
*/
async function resolveAuthorizedSession(
c: Context,
deps: SessionFsDeps | undefined,
workspacePath: string,
): Promise<SourceControlSession | null> {
if (!deps) return null;
const session = await deps.sessions.getBySessionId(workspacePath);
if (!session) return null;
if (deps.auth.enabled()) {
await deps.auth.ensureUser(c);
const tenant = deps.auth.tenant(c);
if (!tenant || tenant.orgId !== session.orgId || tenant.userId !== session.userId) {
throw new Error('Session is not available to the current user');
}
}
return session;
}
export async function listSessionFilesystemFiles(
filesystem: Pick<FilesystemStorage, 'listFiles'>,
session: SourceControlSession,
threadId: string,
): Promise<WorkspaceFilesListing> {
const safeThreadId = threadId.trim();
if (!safeThreadId) throw new Error('Missing required query param: threadId');
// The turn-end capture no longer gates agent_end, so a reader refetching on
// run completion could otherwise race it and serve the previous turn's
// listing. Await the in-flight capture (bounded) before reading.
await waitForPendingFilesystemCapture(session.sessionId);
View on GitHub (pinned to 75dd419e61)
Solutions
- Confirm you are authenticated as the user who owns the session (orgId and userId must both match) — log in as that user or request access.
- Check the auth token/credentials: ensure they are issued for the same organization as the session.
- Verify the session id in workspacePath is yours (list your sessions rather than copying an id from a shared URL).
- If auth headers are being stripped by a proxy, fix proxy configuration so deps.auth.tenant(c) receives a valid tenant.
Example fix
// before: shared link to another user's session GET /fs?workspacePath=<someone-elses-session-id> // → 403-ish 'Session is not available to the current user' // after: use your own session id GET /fs?workspacePath=<your-own-session-id>
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side: only request sessions returned by your own session list
const mySessions = await fetch('/sessions', { headers: authHeaders }).then(r => r.json());
const owns = mySessions.some(s => s.sessionId === workspacePath);
if (!owns) throw new Error('refusing request: session not owned by current user'); Type guard
function isOwnSession(
session: { orgId: string; userId: string },
tenant: { orgId: string; userId: string } | null,
): boolean {
return tenant !== null && tenant.orgId === session.orgId && tenant.userId === session.userId;
} Try / catch
try {
const files = await fetchSessionFiles(workspacePath, threadId);
} catch (e) {
if (e instanceof Error && e.message === 'Session is not available to the current user') {
// treat as 403: re-authenticate with the owning org's credentials or hide the link
return { status: 'forbidden' };
}
throw e;
} Prevention
- Never share or hardcode session ids across users/orgs; fetch session lists per authenticated user.
- Ensure auth headers survive proxies so deps.auth.tenant(c) is populated.
- Re-authenticate after org changes; stale tokens cause tenant mismatch.
- Distinguish null (no such session → local-path fallback) from this throw (exists but not yours) in client logic.
When it happens
Trigger: Requesting session filesystem routes with workspacePath set to another user's session id while authenticated; calling with an unauthenticated/no-tenant context (tenant() returns null) while the session exists; tokens issued for a different org than the one owning the session; stale credentials after the session was transferred or the user's org changed.
Common situations: Sharing a Studio/Factory URL containing a session id with a teammate; using a personal-access token from the wrong organization; a reverse proxy stripping auth headers so tenant() is null; multi-tenant environments where the client cached an old session id.
Related errors
- Factory session ${session.sessionId} is not available to the
- AGENT_MEMORY_THREAD_RESOURCE_MISMATCH
- FGA denied for tool '${resourceId}'
- Thread with id ${threadId} is for resource with id ${thread.
- ${label} is outside the curator's visible scope.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/2876e5d84198e345.
Report an issue: GitHub.