mastra-ai/mastra · error
Version with id ${input.id} already exists
Error message
Version with id ${input.id} already exists What it means
The in-memory scorer-definitions storage createVersion() throws when a version with the same id is already stored in scorerDefinitionVersions. A second check rejects duplicate (scorerDefinitionId, versionNumber) pairs right after. Both keys must be unique for version history to be addressable.
Source
Thrown at packages/core/src/storage/domains/scorer-definitions/inmemory.ts:208
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
return {
scorerDefinitions: clonedScorers.slice(offset, offset + perPage),
total: clonedScorers.length,
page,
perPage: perPageForResponse,
hasMore: offset + perPage < clonedScorers.length,
};
}
// ==========================================================================
// Scorer Definition Version Methods
// ==========================================================================
async createVersion(input: CreateScorerDefinitionVersionInput): Promise<ScorerDefinitionVersion> {
// Check if version with this ID already exists
if (this.db.scorerDefinitionVersions.has(input.id)) {
throw new Error(`Version with id ${input.id} already exists`);
}
// Check for duplicate (scorerDefinitionId, versionNumber) pair
for (const version of this.db.scorerDefinitionVersions.values()) {
if (version.scorerDefinitionId === input.scorerDefinitionId && version.versionNumber === input.versionNumber) {
throw new Error(
`Version number ${input.versionNumber} already exists for scorer definition ${input.scorerDefinitionId}`,
);
}
}
const version: ScorerDefinitionVersion = {
...input,
createdAt: new Date(),
};
// Deep clone before storing
this.db.scorerDefinitionVersions.set(input.id, this.deepCopyVersion(version));View on GitHub (pinned to 75dd419e61)
Solutions
- Generate a fresh unique version id (crypto.randomUUID()) for each createVersion call.
- Compute versionNumber as max(existing versions for the definition)+1 rather than a constant.
- Catch the error and treat it as 'already created' for idempotent replay flows.
- Serialize version creation (or retry on conflict by re-reading current versions) if multiple writers create versions concurrently.
Example fix
// before
await storage.scorerDefinitions.createVersion({ id: 'helpfulness-v1', scorerDefinitionId, versionNumber: 1, config });
// after
const id = crypto.randomUUID();
const existing = await storage.scorerDefinitions.listVersions(scorerDefinitionId);
const versionNumber = existing.versions.reduce((m, v) => Math.max(m, v.versionNumber), 0) + 1;
await storage.scorerDefinitions.createVersion({ id, scorerDefinitionId, versionNumber, config }); Defensive patterns
Strategy: validation
Validate before calling
const { versions } = await storage.scorerDefinitions.listVersions(scorerDefinitionId);
const nextNumber = versions.reduce((m, v) => Math.max(m, v.versionNumber), 0) + 1;
if (versions.some(v => v.id === versionId)) {
throw new Error(`version id ${versionId} already used`);
} Type guard
function versionIdIsFree(versions: { id: string }[], id: string): boolean {
return !versions.some(v => v.id === id);
} Try / catch
try {
await storage.scorerDefinitions.createVersion(input);
} catch (e) {
if (e instanceof Error && e.message.includes('already exists')) {
return; // treat as idempotent success on replay
}
throw e;
} Prevention
- Use crypto.randomUUID() for every version id.
- Compute versionNumber as max+1 from current stored versions, not a constant.
- Make retries idempotent: same input should be safely skippable when the error says 'already exists'.
- Serialize concurrent version creation per scorer definition to avoid races.
When it happens
Trigger: Calling createVersion({ id: 'v1', scorerDefinitionId: 's1', versionNumber: 1, ... }) twice with the same id; re-running seedAgent/create flows that already inserted the version; retrying after a partial success.
Common situations: Re-deploying or re-importing scorer versions with fixed ids; retries without idempotency keys; concurrent writers both computing 'next version' from the same snapshot.
Related errors
- Scorer definition with id ${scorerDefinition.id} already exi
- Version number ${input.versionNumber} already exists for pro
- Schedule ${schedule.id} already exists
- Scorer definition with id ${id} not found
- Version number ${input.versionNumber} already exists for sco
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e9e6293638b1826b.
Report an issue: GitHub.