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

  1. Check existence first (`getWorkspace(id)`) and skip or return the existing workspace.
  2. Generate IDs with `crypto.randomUUID()` rather than fixed names in seed scripts.
  3. Catch the error and treat as idempotent when the existing workspace matches what you'd create.
  4. 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

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


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