{"record":{"id":"386e62d19efef9ed","repo":"mastra-ai/mastra","slug":"prompt-block-with-id-id-already-exists","errorCode":null,"errorMessage":"Prompt block with id ${id} already exists","messagePattern":"Prompt block with id (.+?) already exists","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"error","filePath":"packages/server/src/server/handlers/stored-prompt-blocks.ts","lineNumber":187,"sourceCode":"\n      const promptBlockStore = await storage.getStore('promptBlocks');\n      if (!promptBlockStore) {\n        throw new HTTPException(500, { message: 'Prompt blocks storage domain is not available' });\n      }\n\n      // Derive ID from name if not explicitly provided\n      const id = providedId || toSlug(name);\n\n      if (!id) {\n        throw new HTTPException(400, {\n          message: 'Could not derive prompt block ID from name. Please provide an explicit id.',\n        });\n      }\n\n      // Check if prompt block with this ID already exists\n      const existing = await promptBlockStore.getById(id);\n      if (existing) {\n        throw new HTTPException(409, { message: `Prompt block with id ${id} already exists` });\n      }\n\n      await promptBlockStore.create({\n        promptBlock: {\n          id,\n          authorId,\n          metadata: scopeStoredResourceMetadata(metadata, await getStoredResourceScope(mastra, requestContext)),\n          name,\n          description,\n          content,\n          rules,\n          requestContextSchema,\n        },\n      });\n\n      // Return the resolved prompt block (thin record + version config)\n      // Use draft status since newly created entities start as drafts\n      const resolved = await promptBlockStore.getByIdResolved(id, { status: 'draft' });","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/stored-prompt-blocks.ts#L169-L205","documentation":"The create prompt-block route enforces unique IDs: before inserting, it calls `promptBlockStore.getById(id)` and throws a 409 Conflict if a record with that ID already exists. Unlike some stores, the HTTP create path does not silently upsert — a duplicate ID is a conflict the caller must resolve.","triggerScenarios":"POST /stored/prompt-blocks with an explicit `id` (or a name slugifying to an id) that already matches an existing stored prompt block in the database.","commonSituations":"Re-running a seed/import script without idempotency; two team members creating a block with the same name; retrying a create after a timeout when the first request actually succeeded; name collisions after slugification ('My Block' and 'my block' share the slug 'my-block').","solutions":["Choose a different unique id (or name) for the new prompt block","Check existence first via GET /stored/prompt-blocks/:id and use the update (PUT) route to modify the existing record","Make import scripts idempotent by fetching/updating instead of always creating","Generate ids with a unique suffix (e.g. slug + timestamp or short uuid)"],"exampleFix":"// before\nawait client.createStoredPromptBlock({ id: 'my-prompt', name: 'My Prompt' }) // 409 if exists\n// after\nconst existing = await client.getStoredPromptBlock('my-prompt');\nif (existing) {\n  await client.updateStoredPromptBlock('my-prompt', { /* changes */ });\n} else {\n  await client.createStoredPromptBlock({ id: 'my-prompt', name: 'My Prompt' });\n}","handlingStrategy":"try-catch","validationCode":"const existing = await fetch(`${baseUrl}/api/stored/prompt-blocks/${id}`);\nif (existing.ok) {\n  // conflict: update instead of create\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.createStoredPromptBlock(body);\n} catch (e) {\n  if (isHTTPException(e) && e.status === 409 && e.message.includes('already exists')) {\n    await client.updateStoredPromptBlock(body.id, body);\n    return;\n  }\n  throw e;\n}","preventionTips":["Use GET /stored/prompt-blocks/:id before create in scripts","Generate ids with unique suffixes for non-idempotent imports","Remember slug collisions: 'My Block' and 'my-block' share an id"],"tags":["conflict","duplicate","server"],"backgroundTag":"resource-already-exists","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}