{"record":{"id":"2f082fc40ee8d2a9","repo":"langflow-ai/langflow","slug":"endpoint-name-must-be-unique","errorCode":null,"errorMessage":"Endpoint name must be unique","messagePattern":"Endpoint name must be unique","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"error","filePath":"src/backend/base/langflow/api/v1/flows_helpers.py","lineNumber":235,"sourceCode":"    session: AsyncSession,\n    endpoint_name: str,\n    user_id: UUID,\n    *,\n    fail_on_conflict: bool = False,\n) -> str:\n    \"\"\"Return a unique endpoint name for *user_id*, appending ``-N`` if needed.\n\n    Raises :class:`HTTPException` 409 when *fail_on_conflict* is ``True`` and\n    the name already exists.\n    \"\"\"\n    existing = (\n        await session.exec(select(Flow).where(Flow.endpoint_name == endpoint_name).where(Flow.user_id == user_id))\n    ).first()\n    if not existing:\n        return endpoint_name\n\n    if fail_on_conflict:\n        raise HTTPException(status_code=409, detail=\"Endpoint name must be unique\")\n\n    flows = (\n        await session.exec(\n            select(Flow)\n            .where(Flow.endpoint_name.like(f\"{endpoint_name}-%\"))  # type: ignore[union-attr]\n            .where(Flow.user_id == user_id)\n        )\n    ).all()\n\n    numbers: list[int] = []\n    for f in flows:\n        try:\n            numbers.append(int(f.endpoint_name.split(\"-\")[-1]))\n        except ValueError:\n            continue\n\n    next_num = (max(numbers) + 1) if numbers else 1\n    return f\"{endpoint_name}-{next_num}\"","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/flows_helpers.py#L217-L253","documentation":"HTTP 409 (Conflict) from _deduplicate_endpoint_name: the requested endpoint_name already exists for this user and the caller passed fail_on_conflict=True (the PUT upsert path, which must fail predictably instead of silently renaming). The check is per-user: an exact match on Flow.endpoint_name within the same user_id blocks the request.","triggerScenarios":"PUT /api/v1/flows/{id} (upsert for instance syncing) with endpoint_name that another of your flows already owns; re-running a sync after a partial import duplicated endpoint names.","commonSituations":"Syncing the same flow twice under different flow ids; importing a bundle whose endpoint names collide with existing local flows; renaming a flow to an endpoint_name you already used.","solutions":["Pick a unique endpoint_name before the PUT.","Delete or rename the flow that currently holds the conflicting endpoint_name.","Use POST (create) instead of PUT if you want the -N auto-renaming behaviour instead of a 409.","On 409, GET your flows filtered by endpoint_name to find the collision, then retry with a suffixed name."],"exampleFix":"# before\nPUT /api/v1/flows/{id}  {\"endpoint_name\": \"my-api\"}   # another flow owns it\n# after\nPUT /api/v1/flows/{id}  {\"endpoint_name\": \"my-api-2\"}","handlingStrategy":"validation","validationCode":"const mine = await listFlows();\nif (mine.some(f => f.endpoint_name === body.endpoint_name)) throw new Error('endpoint_name taken');","typeGuard":null,"tryCatchPattern":"try { await putFlow(id, body) } catch (e) { if (e.status === 409) { body.endpoint_name += '-2'; return putFlow(id, body); } throw e; }","preventionTips":["Namespace endpoint names per sync source","Prefer POST (auto-renames -N) when uniqueness is not critical","Resolve collisions before re-running imports"],"tags":["conflict","uniqueness","http-409","endpoint-name","upsert"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}