mastra-ai/mastra · error · HTTPException
Workspace with id ${id} already exists
Error message
Workspace with id ${id} already exists What it means
The workspace creation handler checks workspaceStore.getById(id) before inserting and throws HTTPException 409 when a workspace with the same id already exists. IDs are caller-supplied, so re-creating a workspace with a previously used id collides with the stored record.
Source
Thrown at packages/server/src/server/handlers/stored-workspaces.ts:196
const workspaceStore = await storage.getStore('workspaces');
if (!workspaceStore) {
throw new HTTPException(500, { message: 'Workspaces storage domain is not available' });
}
// Derive ID from name if not explicitly provided
const id = providedId || toSlug(name);
if (!id) {
throw new HTTPException(400, {
message: 'Could not derive workspace ID from name. Please provide an explicit id.',
});
}
// Check if workspace with this ID already exists
const existing = await workspaceStore.getById(id);
if (existing) {
throw new HTTPException(409, { message: `Workspace with id ${id} already exists` });
}
// Force authorId from the authenticated caller; ignore any body-provided value.
// No caller (auth not configured) leaves authorId undefined so legacy
// single-user setups continue to behave as today.
const authorId = getCallerAuthorId(requestContext) ?? undefined;
await workspaceStore.create({
workspace: {
id,
authorId,
metadata: scopeStoredResourceMetadata(metadata, await getStoredResourceScope(mastra, requestContext)),
name,
description,
filesystem,
sandbox,
mounts,
search,View on GitHub (pinned to 75dd419e61)
Solutions
- Use a different, unique id for the new workspace (e.g. prefix a UUID or timestamp).
- Call getById or the list endpoint first to confirm the id is free before creating.
- If the existing workspace is stale, delete it first, then re-create with the same id.
- Handle HTTP 409 in the client and treat it as 'already exists' rather than retrying blindly.
Example fix
// before
await createWorkspace({ id: 'my-workspace', name: 'My Workspace' });
// after
const existing = await client.getWorkspace('my-workspace').catch(() => null);
if (!existing) {
await createWorkspace({ id: 'my-workspace', name: 'My Workspace' });
} Defensive patterns
Strategy: try-catch
Validate before calling
const existing = await client.getWorkspace(id).catch(() => null);
if (existing) throw new Error(`Workspace ${id} already exists; pick another id`); Try / catch
try {
await client.createWorkspace({ id, name });
} catch (e) {
if (e.status === 409) {
// id taken: regenerate or treat as already-provisioned
id = crypto.randomUUID();
await client.createWorkspace({ id, name });
} else throw e;
} Prevention
- Generate ids (UUID/ULID) instead of human-chosen names.
- Use create-or-get logic for idempotent provisioning scripts.
- Check for existence before creating in retry loops.
When it happens
Trigger: POST to the stored-workspaces create endpoint with a body id that matches an existing workspace record in the workspaces storage domain.
Common situations: Re-running an idempotent provisioning script without a unique suffix; copy-pasting a create request in a retry loop after a timeout that actually succeeded; two clients choosing the same human-readable id.
Related errors
- Scorer definition with id ${id} already exists
- Skill with id ${id} already exists
- EXPERIMENT_ID_CONFLICT
- Agent with id ${input.agent.id} already exists
- Version number ${input.versionNumber} already exists for age
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/59852e41e7eb2bd9.
Report an issue: GitHub.