mastra-ai/mastra · error
Workspace with id ${workspace.id} already exists
Error message
Workspace with id ${workspace.id} already exists What it means
`create` in the workspaces storage enforces unique workspace IDs: if `this.db.workspaces` already holds `workspace.id`, it throws instead of overwriting. Workspace IDs are primary keys, so duplicates indicate an id-generation or retry bug.
Source
Thrown at packages/core/src/storage/domains/workspaces/inmemory.ts:49
async dangerouslyClearAll(): Promise<void> {
this.db.workspaces.clear();
this.db.workspaceVersions.clear();
}
// ==========================================================================
// Workspace CRUD Methods
// ==========================================================================
async getById(id: string): Promise<StorageWorkspaceType | null> {
const config = this.db.workspaces.get(id);
return config ? this.deepCopyConfig(config) : null;
}
async create(input: { workspace: StorageCreateWorkspaceInput }): Promise<StorageWorkspaceType> {
const { workspace } = input;
if (this.db.workspaces.has(workspace.id)) {
throw new Error(`Workspace with id ${workspace.id} already exists`);
}
const now = new Date();
const newConfig: StorageWorkspaceType = {
id: workspace.id,
status: 'draft',
activeVersionId: undefined,
authorId: workspace.authorId,
metadata: workspace.metadata,
createdAt: now,
updatedAt: now,
};
this.db.workspaces.set(workspace.id, newConfig);
// Extract config fields from the flat input (everything except record fields)
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = workspace;
View on GitHub (pinned to 75dd419e61)
Solutions
- Check existence first (`getWorkspace(id)`) and skip or return the existing workspace.
- Generate IDs with `crypto.randomUUID()` rather than fixed names in seed scripts.
- Catch the error and treat as idempotent when the existing workspace matches what you'd create.
- Guard app initialization so bootstrap/seeding runs only once per process.
Example fix
// before
await storage.create({ workspace: { id: 'default', name: 'Default' } }); // throws on re-run
// after
const existing = await storage.getWorkspace('default');
if (!existing) await storage.create({ workspace: { id: 'default', name: 'Default' } }); Defensive patterns
Strategy: fallback
Validate before calling
async function getOrCreateWorkspace(storage, workspace) {
const existing = await storage.getWorkspace(workspace.id);
if (existing) return existing;
return storage.create({ workspace });
} Try / catch
try {
return await storage.create({ workspace });
} catch (err) {
if (err instanceof Error && err.message.startsWith('Workspace with id')) {
return storage.getWorkspace(workspace.id); // already exists: idempotent
}
throw err;
} Prevention
- Make bootstrap/seed code idempotent: check existence before create.
- Use UUIDs for workspace IDs in tests and seeds, or run seeding only once.
- Guard initialization with a once-flag so app startup can't double-create.
When it happens
Trigger: Calling `create({ workspace: { id: '<existing-id>', ... } })` where a workspace with that ID already exists, including via `seedAgent` flows that regenerate fixed IDs.
Common situations: Re-running seed/bootstrap scripts with hard-coded workspace IDs (e.g. 'default'), retrying a create request that already succeeded, or app initialization code running twice in the same process.
Related errors
- Skill with id ${skill.id} already exists
- Version with id ${input.id} already exists
- Agent with id ${input.agent.id} already exists
- Version with id ${input.id} already exists
- Version with id ${input.id} already exists
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/49df9b8fb880926b.
Report an issue: GitHub.