mastra-ai/mastra · error · Error

Version with id ${input.id} already exists

Error message

Version with id ${input.id} already exists

What it means

createVersion() checks the memory store for an existing version with the same version id before inserting. If a version record with that id already exists, it throws to preserve version-record uniqueness. This prevents duplicate/idempotent-replay writes from corrupting version history.

Source

Thrown at packages/core/src/storage/domains/agents/source.ts:251

      if (this.providerVersions.get(versionId)?.agentId === id) {
        this.providerVersions.delete(versionId);
      }
    }
    await this.memory.delete(id);
  }

  async list(args?: StorageListAgentsInput): Promise<StorageListAgentsOutput> {
    this.refreshKnownAgentIds();
    await this.discoverProviderAgentIds();
    await Promise.all([...this.knownAgentIds].map(agentId => this.hydrateAgent(agentId)));
    return this.memory.list(args);
  }

  async createVersion(input: CreateVersionInput): Promise<AgentVersion> {
    await this.hydrateAgent(input.agentId);
    const existingVersion = await this.memory.getVersion(input.id);
    if (existingVersion) {
      throw new Error(`Version with id ${input.id} already exists`);
    }
    const existingVersionNumber = await this.memory.getVersionByNumber(input.agentId, input.versionNumber);
    if (existingVersionNumber) {
      throw new Error(`Version number ${input.versionNumber} already exists for agent ${input.agentId}`);
    }

    const snapshot = snapshotFromVersion({ ...input, createdAt: new Date() } as AgentVersion);
    const result = await this.persistSnapshot(input.agentId, snapshot, input.changeMessage);
    const version = await this.memory.createVersion(input);
    this.rememberProviderVersion(input.agentId, version, result);
    return version;
  }

  async getVersion(id: string): Promise<AgentVersion | null> {
    const providerVersion = this.providerVersions.get(id);
    if (providerVersion) {
      return structuredClone(providerVersion);
    }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Generate a genuinely unique version id (UUID) for each version
  2. Fetch the existing version and reuse it instead of creating a new one
  3. Make the call idempotent: catch this error and treat the version as already recorded
  4. Fix retry logic to not blindly replay writes with the same id

Example fix

// before
await storage.agents.createVersion({ id: fixedId, agentId, versionNumber: 2, ... })
// after
const id = crypto.randomUUID();
await storage.agents.createVersion({ id, agentId, versionNumber: 2, ... });
Defensive patterns

Strategy: try-catch

Validate before calling

const existing = await memory.getVersion(input.id);
if (existing) return existing; // already recorded

Type guard

null

Try / catch

try {
  await storage.agents.createVersion(input);
} catch (e) {
  if (e.message === `Version with id ${input.id} already exists`) return; // idempotent replay
  throw e;
}

Prevention

When it happens

Trigger: Calling storage.agents.version()/createVersion() with input.id matching an already-stored AgentVersion id (after hydrating the agent).

Common situations: Retrying a createVersion call after a network/timeout where the first write succeeded, generating version ids non-uniquely (e.g. from timestamps with low resolution), replaying an event or migration twice.

Related errors


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