{"record":{"id":"c952d7153af0744b","repo":"mastra-ai/mastra","slug":"version-number-input-versionnumber-already-exis-c952d7","errorCode":null,"errorMessage":"Version number ${input.versionNumber} already exists for prompt block ${input.blockId}","messagePattern":"Version number (.+?) already exists for prompt block (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/domains/prompt-blocks/inmemory.ts","lineNumber":186,"sourceCode":"      perPage: perPageForResponse,\n      hasMore: offset + perPage < clonedBlocks.length,\n    };\n  }\n\n  // ==========================================================================\n  // Prompt Block Version Methods\n  // ==========================================================================\n\n  async createVersion(input: CreatePromptBlockVersionInput): Promise<PromptBlockVersion> {\n    // Check if version with this ID already exists\n    if (this.db.promptBlockVersions.has(input.id)) {\n      throw new Error(`Version with id ${input.id} already exists`);\n    }\n\n    // Check for duplicate (blockId, versionNumber) pair\n    for (const version of this.db.promptBlockVersions.values()) {\n      if (version.blockId === input.blockId && version.versionNumber === input.versionNumber) {\n        throw new Error(`Version number ${input.versionNumber} already exists for prompt block ${input.blockId}`);\n      }\n    }\n\n    const version: PromptBlockVersion = {\n      ...input,\n      createdAt: new Date(),\n    };\n\n    // Deep clone before storing\n    this.db.promptBlockVersions.set(input.id, this.deepCopyVersion(version));\n    return this.deepCopyVersion(version);\n  }\n\n  async getVersion(id: string): Promise<PromptBlockVersion | null> {\n    const version = this.db.promptBlockVersions.get(id);\n    return version ? this.deepCopyVersion(version) : null;\n  }\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/domains/prompt-blocks/inmemory.ts#L168-L204","documentation":"InMemoryPromptBlockStorage.createVersion() throws this when a version with the same (blockId, versionNumber) pair already exists in the promptBlockVersions store. The library enforces unique version numbers per prompt block so version history stays monotonic and addressable. The version id is checked separately just before this check.","triggerScenarios":"Calling storage.promptBlocks.createVersion({ id: newId, blockId: 'b1', versionNumber: 2, ... }) when a version with blockId 'b1' and versionNumber 2 was already created (e.g. by a prior createVersion call or a seed routine like seedAgent that calls create->createVersion internally).","commonSituations":"Re-running a seeding/import script without clearing the store; retrying a failed request after the first attempt actually succeeded; concurrent writers racing to insert the next version number; hardcoding versionNumber instead of computing max+1.","solutions":["Query listVersions(blockId) first and compute the next versionNumber as max(existing)+1 before calling createVersion.","Generate a fresh version id (crypto.randomUUID()) so the id-uniqueness check never collides, and only reuse versionNumber for idempotent replays you intend to reject.","Wrap createVersion in try-catch and treat this message as 'already applied' if the replay is intentional.","Clear the in-memory store (or use a fresh instance) between test/seed runs."],"exampleFix":"// before\nawait storage.promptBlocks.createVersion({ id, blockId, versionNumber: 2, content });\n// after\nconst { versions } = await storage.promptBlocks.listVersions(blockId, { perPage: false });\nconst next = versions.reduce((m, v) => Math.max(m, v.versionNumber), 0) + 1;\nawait storage.promptBlocks.createVersion({ id: crypto.randomUUID(), blockId, versionNumber: next, content });","handlingStrategy":"validation","validationCode":"const { versions } = await storage.promptBlocks.listVersions(blockId, { perPage: false });\nif (versions.some(v => v.versionNumber === nextVersionNumber)) {\n  throw new Error(`versionNumber ${nextVersionNumber} already used for block ${blockId}`);\n}","typeGuard":"function versionNumberIsFree(versions: { versionNumber: number }[], n: number): boolean {\n  return !versions.some(v => v.versionNumber === n);\n}","tryCatchPattern":"try {\n  await storage.promptBlocks.createVersion(input);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('already exists for prompt block')) {\n    return; // idempotent replay: version already recorded\n  }\n  throw e;\n}","preventionTips":["Always derive versionNumber from existing versions (max+1), never hardcode it.","Use crypto.randomUUID() for version ids.","Make seed/import scripts idempotent or guard them with an existence check.","Use a fresh in-memory storage instance per test to avoid cross-test residue."],"tags":["storage","duplicate-key","prompt-blocks","in-memory"],"backgroundTag":"duplicate-version-number","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}