langfuse/langfuse · error

name_conflict

name_conflict

Error message

An evaluation rule named "${params.input.name}" already exists in this project. Use PATCH /api/public/unstable/evaluation-rules/${existing.id} to update it instead of creating a duplicate.

What it means

409 name_conflict when creating an evaluation rule whose name already exists for an event/experiment target rule in the project. The message points to the PATCH endpoint of the existing rule.

Source

Thrown at web/src/features/evals/server/unstable-public-api/evaluation-rule-service.ts:324

  input: PostUnstableEvaluationRuleBodyType;
  evaluatorId?: string;
  auditScope?: Pick<ApiAccessScope, "orgId" | "apiKeyId">;
}) {
  // Scoped to the targets this API can write. Rule names carry no uniqueness constraint, so this
  // only exists to hand back the id to PATCH instead of a second rule -- and PATCH 404s on the
  // trace/dataset rules the backfill brought in, so including those would be a dead end.
  const existing = await prisma.evaluationRule.findFirst({
    where: {
      projectId: params.projectId,
      name: params.input.name,
      targetObject: {
        in: [EvalTargetObject.EVENT, EvalTargetObject.EXPERIMENT],
      },
    },
    select: { id: true },
  });
  if (existing) {
    throw createStructuredPublicApiError({
      httpCode: 409,
      code: "name_conflict",
      message: `An evaluation rule named "${params.input.name}" already exists in this project. Use PATCH /api/public/unstable/evaluation-rules/${existing.id} to update it instead of creating a duplicate.`,
      details: { field: "name" },
    });
  }
  if (params.input.enabled) {
    await assertActivePublicApiEvaluationRuleLimitNotExceeded(params.projectId);
  }
  await assertEvaluationRuleFilterValuesExistForProject({
    projectId: params.projectId,
    target: params.input.target,
    filters: params.input.filter,
  });

  const requestedAssignments = getRequestedEvaluatorAssignments(params.input);
  const evaluators = await Promise.all(
    requestedAssignments.map(({ evaluator }, index) =>

View on GitHub (pinned to 59d92c7cf3)

Solutions

  1. Use PATCH /api/public/unstable/evaluation-rules/{id} with the id from the error message instead of POST
  2. Pick a unique rule name
  3. Delete the existing rule first if it is obsolete

Example fix

// before
POST /api/public/unstable/evaluation-rules { name: "daily-eval", ... }
// after
PATCH /api/public/unstable/evaluation-rules/<existing.id> { ... }
Defensive patterns

Strategy: validation

Validate before calling

const existing = await findRuleByName(name);
if (existing) return patchRule(existing.id, body);
await createRule({ ...body, name });

Try / catch

try { await createRule(body); } catch (e) { if (e?.error?.code === "name_conflict") { const id = e.error.message.match(/evaluation-rules\/([\w-]+)/)?.[1]; await patchRule(id, body); } else throw e; }

Prevention

When it happens

Trigger: POST /api/public/unstable/evaluation-rules with a name that matches an existing EVENT/EXPERIMENT-target rule in the same project.

Common situations: Re-running setup scripts that create rules idempotently-by-name; migrating configs between environments.

Related errors


AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27). Data as JSON: /api/errors/ddb5426694f25751. Report an issue: GitHub.