{"record":{"id":"3a76d4b1c618c8a0","repo":"langfuse/langfuse","slug":"multiple-evaluators-named-input-name-exist-in","errorCode":null,"errorMessage":"Multiple evaluators named \"${input.name}\" exist in this project","messagePattern":"Multiple evaluators named \"(.+?)\" exist in this project","errorType":"http","errorClass":"LangfuseConflictError","httpStatus":409,"severity":"error","filePath":"web/src/features/evals/v2/server/evaluators/evaluatorService.ts","lineNumber":299,"sourceCode":"    });\n    return evaluator;\n  }\n\n  // Temporary fallback for the unstable Evaluators API until the final API\n  // exposes explicit create and update semantics.\n  async upsertByName(\n    input: CreateEvaluatorInput,\n    createdByUserId: string | null,\n  ) {\n    const block = await validateEvaluatorForPersistence(input);\n    const result = await this.prisma.$transaction(async (prisma) => {\n      const matches = await repository.findEvaluatorsByName({\n        prisma,\n        projectId: input.projectId,\n        name: input.name,\n      });\n      if (matches.length > 1) {\n        throw new LangfuseConflictError(\n          `Multiple evaluators named \"${input.name}\" exist in this project`,\n        );\n      }\n\n      const existing = matches[0];\n      if (!existing) {\n        return {\n          action: \"create\" as const,\n          evaluator: await repository.createEvaluator({\n            prisma,\n            input: {\n              ...input,\n              definition: prepareEvaluatorDefinitionForPersistence(\n                input.definition,\n              ),\n            },\n            createdByUserId,\n            block,","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/langfuse/langfuse/blob/59d92c7cf365150d10b753b5a0d1708902a2ed60/web/src/features/evals/v2/server/evaluators/evaluatorService.ts#L281-L317","documentation":"upsertByName looks up evaluators by project + name and throws LangfuseConflictError when more than one match exists, because name-based upsert is only safe when the name unambiguously identifies a single evaluator.","triggerScenarios":"Calling upsertByName (create/update evaluator by name) when the project already contains two or more evaluators sharing that name — usually from before a unique-name constraint existed, or created via direct API with explicit distinct ids.","commonSituations":"Historic data with duplicate names in one project; migrating to name-based upsert on an old project; concurrent creation of same-named evaluators via id-based create.","solutions":["Rename or delete the duplicate evaluators so the name is unique within the project, then retry the upsert","Prefer id-based create/update when duplicate names are expected","Guard UI flows that rename evaluators from enforcing name uniqueness"],"exampleFix":"// before\nawait evaluatorService.upsertByName({ projectId, name: \"accuracy\", ... });\n// after\nconst dupes = await repository.findEvaluatorsByName({ prisma, projectId, name: \"accuracy\" });\nif (dupes.length > 1) throw new Error(\"Resolve duplicate evaluators named 'accuracy' first\");\nawait evaluatorService.upsertByName({ projectId, name: \"accuracy\", ... });","handlingStrategy":"validation","validationCode":"const matches = await repository.findEvaluatorsByName({ prisma, projectId, name: input.name });\nif (matches.length > 1) throw new Error(`Resolve ${matches.length} duplicates named \"${input.name}\" before upsert`);","typeGuard":"null","tryCatchPattern":"try { await evaluatorService.upsertByName(input); } catch (e) { if (e instanceof LangfuseConflictError && e.message.startsWith(\"Multiple evaluators\")) { /* list duplicates for the user to rename/delete */ } else throw e; }","preventionTips":["Enforce unique evaluator names per project in the UI and API","Before adopting name-based upsert, run a duplicate-name audit per project","Prefer id-based updates in automation"],"tags":["evals","conflict","duplicate-name","upsert"],"backgroundTag":"ambiguous-unique-key-upsert","analyzedSha":"59d92c7cf365150d10b753b5a0d1708902a2ed60","analyzedAt":"2026-08-27T22:22:00.402Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}