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
- Generate a genuinely unique version id (UUID) for each version
- Fetch the existing version and reuse it instead of creating a new one
- Make the call idempotent: catch this error and treat the version as already recorded
- 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
- Generate version ids with crypto.randomUUID()
- Treat createVersion as idempotent in retry logic
- Never derive ids from low-resolution timestamps
- Log version ids on first write to correlate retries
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
- Agent with id ${input.agent.id} already exists
- Version number ${input.versionNumber} already exists for age
- Version number ${input.versionNumber} already exists for ski
- Version with id ${input.id} already exists
- Version number ${input.versionNumber} already exists for wor
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b217184db8d5ed4f.
Report an issue: GitHub.