mastra-ai/mastra · error
${this.name}: version number ${input.versionNumber} already
Error message
${this.name}: version number ${input.versionNumber} already exists for entity ${parentId} What it means
createVersion scans all stored versions and rejects a new version whose (parentId, versionNumber) pair matches an existing one. Even with unique ids, version numbers must be unique per entity so history ordering stays deterministic.
Source
Thrown at packages/core/src/storage/filesystem-versioned.ts:612
};
}
// ==========================================================================
// Version Methods (in-memory + git history)
// ==========================================================================
async createVersion(input: TVersion): Promise<TVersion> {
await this.ensureGitHistory();
if (this.versions.has(input.id)) {
throw new Error(`${this.name}: version with id ${input.id} already exists`);
}
const parentId = (input as Record<string, unknown>)[this.parentIdField] as string;
// Check for duplicate (parentId, versionNumber) pair
for (const v of this.versions.values()) {
if ((v as Record<string, unknown>)[this.parentIdField] === parentId && v.versionNumber === input.versionNumber) {
throw new Error(`${this.name}: version number ${input.versionNumber} already exists for entity ${parentId}`);
}
}
const version: TVersion = {
...input,
createdAt: new Date(),
} as TVersion;
this.versions.set(input.id, structuredClone(version));
return structuredClone(version);
}
async getVersion(id: string): Promise<TVersion | null> {
await this.ensureGitHistory();
return this.versions.has(id) ? structuredClone(this.versions.get(id)!) : null;
}
async getVersionByNumber(entityId: string, versionNumber: number): Promise<TVersion | null> {View on GitHub (pinned to 75dd419e61)
Solutions
- Query listVersions for the entity and compute nextVersionNumber = max(existing) + 1 before creating.
- Serialize writes per entity (lock/queue) if multiple processes can create versions concurrently.
- Catch the error, re-read current max version number, and retry with the incremented value.
Example fix
// before
await store.createVersion({ id: vId, [parentIdField]: entityId, versionNumber: 3 });
// after
const { versions } = await store.listVersions({ [parentIdField]: entityId });
const next = Math.max(0, ...versions.map(v => v.versionNumber)) + 1;
await store.createVersion({ id: vId, [parentIdField]: entityId, versionNumber: next }); Defensive patterns
Strategy: validation
Validate before calling
const { versions } = await store.listVersions({ [parentIdField]: entityId });
const next = Math.max(0, ...versions.map(v => v.versionNumber)) + 1;
if (newVersionNumber !== next) throw new Error(`Expected versionNumber ${next}`); Try / catch
try {
await store.createVersion(version);
} catch (e) {
if (String(e.message).includes('already exists for entity')) {
// recompute next version number and retry once
} else throw e;
} Prevention
- Always derive the next versionNumber from listVersions output, never from client state.
- Serialize version creation per entity in concurrent environments.
- Retry with recomputed version number on conflict.
When it happens
Trigger: Creating two versions with the same versionNumber for the same parent entity; concurrent writers both assigning versionNumber N to the same entity; an import replaying versions of an entity.
Common situations: Manual version increments that didn't account for the latest stored version; optimistic client computing next versionNumber from stale data; parallel CI jobs writing to the same entity.
Related errors
- Version number ${input.versionNumber} already exists for age
- EXPERIMENT_ID_CONFLICT
- DATASET_ITEM_NOT_FOUND
- Version with id ${input.id} already exists
- Version number ${input.versionNumber} already exists for age
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4046130205ff9e2d.
Report an issue: GitHub.