mastra-ai/mastra · error
Version with id ${input.id} already exists
Error message
Version with id ${input.id} already exists What it means
`createVersion` enforces that skill version IDs are unique within the in-memory store. If `this.db.skillVersions` already contains a version with `input.id`, it throws before inserting. This prevents silently overwriting an existing immutable version record.
Source
Thrown at packages/core/src/storage/domains/skills/inmemory.ts:315
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
return {
skills: clonedConfigs.slice(offset, offset + perPage),
total: clonedConfigs.length,
page,
perPage: perPageForResponse,
hasMore: offset + perPage < clonedConfigs.length,
};
}
// ==========================================================================
// Skill Version Methods
// ==========================================================================
async createVersion(input: CreateSkillVersionInput): Promise<SkillVersion> {
// Check if version with this ID already exists
if (this.db.skillVersions.has(input.id)) {
throw new Error(`Version with id ${input.id} already exists`);
}
// Check for duplicate (skillId, versionNumber) pair
for (const version of this.db.skillVersions.values()) {
if (version.skillId === input.skillId && version.versionNumber === input.versionNumber) {
throw new Error(`Version number ${input.versionNumber} already exists for skill ${input.skillId}`);
}
}
const version: SkillVersion = {
...input,
createdAt: new Date(),
};
// Deep clone before storing
this.db.skillVersions.set(input.id, this.deepCopyVersion(version));
return this.deepCopyVersion(version);
}View on GitHub (pinned to 75dd419e61)
Solutions
- Generate a unique version ID (UUID/nanoid) instead of a deterministic reused one.
- Before inserting, check existence with `getVersion(input.id)` and update or skip instead of creating.
- Wrap the call in try/catch and treat the duplicate-ID error as idempotent success if the existing record matches.
- For seed scripts, clear skillVersions or use upsert semantics before re-seeding.
Example fix
// before
await storage.createVersion({ id: 'my-skill-1', skillId: 'my-skill', versionNumber: 1 });
// after
const existing = await storage.getVersion('my-skill-1');
if (!existing) await storage.createVersion({ id: crypto.randomUUID(), skillId: 'my-skill', versionNumber: 1 }); Defensive patterns
Strategy: fallback
Validate before calling
async function createVersionIfAbsent(storage, input) {
const existing = await storage.getVersion(input.id);
if (existing) return existing;
return storage.createVersion(input);
} Try / catch
try {
await storage.createVersion(input);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Version with id')) {
return storage.getVersion(input.id); // idempotent: return existing
}
throw err;
} Prevention
- Use random UUIDs for version IDs instead of deterministic names.
- Make seed scripts idempotent: check-then-create or clear the store first.
- Serialize version creation for the same skill (single writer/queue).
When it happens
Trigger: Calling `createVersion({ id: '<already-used-id>', ... })`, or calling the public `create`/`update` methods that internally invoke `createVersion` with an ID that already exists in storage.
Common situations: Re-running seed/fixture scripts that generate deterministic IDs (e.g. `skill-v1`) without clearing the store, retrying a failed request after the first attempt actually succeeded, or concurrent writers racing to insert the same version ID.
Related errors
- Skill with id ${skill.id} already exists
- Workspace with id ${workspace.id} already exists
- Agent with id ${input.agent.id} already exists
- Version with id ${input.id} already exists
- Version with id ${input.id} already exists
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/66c56c0610b7d62d.
Report an issue: GitHub.