Budibase/budibase · warning · HTTPError
Operation with name '${operationName?.trim()}' already exist
Error message
Operation with name '${operationName?.trim()}' already exists. What it means
assertUniqueOperationName enforces unique operation names per agent, case-insensitively (trimmed, lowercased). When another operation on the same agent (excluding the one being updated) normalizes to the same name, it throws a 400 HTTPError naming the conflicting name.
Source
Thrown at packages/server/src/sdk/workspace/ai/agents/operations.ts:62
const assertUniqueOperationName = (
agent: Agent,
operationName: string | undefined,
excludedOperationId?: string
) => {
const normalizedName = normalizeOperationName(operationName)
if (!normalizedName) {
return
}
const hasDuplicateName = (agent.operations ?? []).some(operation => {
return (
operation.id !== excludedOperationId &&
normalizeOperationName(operation.name) === normalizedName
)
})
if (hasDuplicateName) {
throw new HTTPError(
`Operation with name '${operationName?.trim()}' already exists.`,
400
)
}
}
export async function createOperation(
agentId: string,
operation: CreateAgentOperationInput
): Promise<Agent> {
const existing = await getOrThrow(agentId)
if (existing.operations?.some(candidate => candidate.id === operation.id)) {
throw new HTTPError("Operation already exists", 400)
}
assertUniqueOperationName(existing, operation.name)
return update({
...existing,View on GitHub (pinned to a81a902e9a)
Solutions
- Check the agent's existing operation names (normalized) before create/rename and pick a unique name.
- If updating, ensure the name check excludes only the operation being edited - rename to something not used by others.
- Catch the 400 HTTPError and show a 'name already in use' validation message to the user.
Example fix
// before
await updateOperation(agentId, opId, { name: existingName }) // 400
// after
const name = "Run Report 2"
const clash = agent.operations?.some(o => o.id !== opId && o.name?.trim().toLowerCase() === name.trim().toLowerCase())
if (clash) throw new HTTPError("Name in use", 400)
await updateOperation(agentId, opId, { name }) Defensive patterns
Strategy: validation
Validate before calling
const norm = (n?: string) => n?.trim().toLowerCase() || ""
const isNameFree = (agent: Agent, name: string, excludeId?: string) =>
!(agent.operations ?? []).some(o => o.id !== excludeId && norm(o.name) === norm(name))
if (!isNameFree(agent, newName, opId)) {
throw new HTTPError("Name already in use", 400)
} Type guard
const isUniqueName = (agent: Agent, name: string, excludeId?: string): boolean =>
!(agent.operations ?? []).some(
o => o.id !== excludeId && o.name?.trim().toLowerCase() === name.trim().toLowerCase()
) Try / catch
try {
await createOperation(agentId, { id, name })
} catch (err) {
if (err instanceof HTTPError && err.status === 400 && err.message.includes("already exists")) {
// prompt user for a different name
}
} Prevention
- Enforce name uniqueness in UI forms with live validation against existing operations.
- Always compare names trimmed and lowercased, matching server normalization.
- In imports, auto-suffix duplicate names instead of failing.
When it happens
Trigger: createOperation with a name that collides with an existing operation on the agent, or updateOperation renaming an operation to a name already used by a sibling operation (case/whitespace differences still collide).
Common situations: Users renaming 'Run Report' to 'run report' which clashes with an existing 'Run Report'; bulk-importing operations with duplicate labels; API integrations generating non-unique names.
Related errors
- Agent with name '${name}' already exists.
- Invalid bookmark query
- Invalid limit query
- Limit query must be between 1 and 100
- Invalid ${queryName} query
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/48737b62c365f7f6.
Report an issue: GitHub.