mastra-ai/mastra · error

Version number ${input.versionNumber} already exists for wor

Error message

Version number ${input.versionNumber} already exists for workspace ${input.workspaceId}

What it means

createVersion() enforces a composite uniqueness rule: (workspaceId, versionNumber) pairs must be unique. Reusing a version number within the same workspace would make version ordering and diffing ambiguous, so it throws.

Source

Thrown at packages/core/src/storage/domains/workspaces/inmemory.ts:258

      perPage: perPageForResponse,
      hasMore: offset + perPage < clonedConfigs.length,
    };
  }

  // ==========================================================================
  // Workspace Version Methods
  // ==========================================================================

  async createVersion(input: CreateWorkspaceVersionInput): Promise<WorkspaceVersion> {
    // Check if version with this ID already exists
    if (this.db.workspaceVersions.has(input.id)) {
      throw new Error(`Version with id ${input.id} already exists`);
    }

    // Check for duplicate (workspaceId, versionNumber) pair
    for (const version of this.db.workspaceVersions.values()) {
      if (version.workspaceId === input.workspaceId && version.versionNumber === input.versionNumber) {
        throw new Error(`Version number ${input.versionNumber} already exists for workspace ${input.workspaceId}`);
      }
    }

    const version: WorkspaceVersion = {
      ...input,
      createdAt: new Date(),
    };

    // Deep clone before storing
    this.db.workspaceVersions.set(input.id, this.deepCopyVersion(version));
    return this.deepCopyVersion(version);
  }

  async getVersion(id: string): Promise<WorkspaceVersion | null> {
    const version = this.db.workspaceVersions.get(id);
    return version ? this.deepCopyVersion(version) : null;
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Fetch the latest version and use versionNumber: (latest?.versionNumber ?? 0) + 1
  2. Catch this error to detect a concurrently-created version, then re-read latest and retry with the incremented number
  3. Deduplicate imported version data on (workspaceId, versionNumber) before insertion
  4. Give each test fixture its own storage instance or unique workspace ids

Example fix

// before
await storage.workspaces.createVersion({ id: crypto.randomUUID(), workspaceId, versionNumber: 1, config });
// after
const latest = await storage.workspaces.getLatestVersion(workspaceId);
await storage.workspaces.createVersion({
  id: crypto.randomUUID(),
  workspaceId,
  versionNumber: (latest?.versionNumber ?? 0) + 1,
  config,
});
Defensive patterns

Strategy: try-catch

Validate before calling

const latest = await storage.workspaces.getLatestVersion(workspaceId);
const next = (latest?.versionNumber ?? 0) + 1;
const clash = (await storage.workspaces.listVersions(workspaceId)).versions.some(v => v.versionNumber === next);
if (clash) throw new Error(`versionNumber ${next} already taken for workspace ${workspaceId}`);

Try / catch

try {
  await storage.workspaces.createVersion(input);
} catch (err) {
  if (err instanceof Error && /already exists for workspace/.test(err.message)) {
    const latest = await storage.workspaces.getLatestVersion(input.workspaceId);
    return storage.workspaces.createVersion({ ...input, versionNumber: (latest?.versionNumber ?? 0) + 1 });
  }
  throw err;
}

Prevention

When it happens

Trigger: Inserting two versions with versionNumber: 1 for the same workspace (e.g. fixture reuse); manually specifying versionNumber instead of computing nextVersion = latest.versionNumber + 1; concurrent createVersion calls racing on the same next number (no lock in the in-memory path).

Common situations: Replaying version history from an export; test suites sharing one storage instance across cases that each seed 'v1'; code that hardcodes versionNumber: 1 for 'initial version' multiple times.

Related errors


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