windmill-labs/windmill · error · Error
A ${existing.resource_type} resource already exists at ${pat
Error message
A ${existing.resource_type} resource already exists at ${path}. Pick another path. What it means
persist() refuses to overwrite an existing resource at the target path when its resource_type is not 'ai_agent'. Because the drawer's path-uniqueness check is debounced, a fast save can race past it, so this server-side re-check prevents clobbering a resource of a different type.
Source
Thrown at frontend/src/lib/components/flows/content/AgentResourceBar.svelte:275
// flow expressions) as authored. Host flows override per-step via tool_inputs, never here.
const value = inputTransformsToAgentConfig(inputTransforms, tools)
// The editor stays live during the requests below, so remember what linking would discard:
// every brain transform and the tools. Comparing the saved config instead would miss a
// non-static brain edit, which the resource cannot hold yet linking still strips.
const savedSnapshot = discardedOnLinkSnapshot()
// If the edit session ends or changes while the requests below are in flight (Cancel, undo,
// session-draft sync, a different agent opened for editing), the resource is still written but
// the step must not be relinked/cleared. Pinning the path — not merely "some edit is active" —
// is what distinguishes this session from a replacement one.
const forkMarker = tools
const savingEditPath = getAgentEditingPath(forkMarker)
const exists = await ResourceService.existsResource({ workspace: ws!, path })
if (exists) {
// The drawer's path check is debounced, so a fast save can reach here with an unrelated
// resource at the path — never clobber a resource of another type.
const existing = await ResourceService.getResource({ workspace: ws!, path })
if (existing.resource_type !== 'ai_agent') {
throw new Error(
`A ${existing.resource_type} resource already exists at ${path}. Pick another path.`
)
}
await ResourceService.updateResourceValue({
workspace: ws!,
path,
requestBody: { value }
})
} else {
await ResourceService.createResource({
workspace: ws!,
requestBody: {
path,
value,
resource_type: 'ai_agent',
description: description || 'Reusable AI agent'
}
})View on GitHub (pinned to e474e8803c)
Solutions
- Pick a different path that is not already occupied by another resource type
- Wait for the drawer's debounced path-availability check to clear before saving
- Delete/rename the conflicting resource at that path if it is no longer needed
Example fix
// before
await persist(newPath)
// after
const exists = await ResourceService.existsResource({ workspace: ws, path: newPath })
if (exists) {
sendUserToast('Path already in use by another resource, pick another path', true)
return
}
await persist(newPath) Defensive patterns
Strategy: validation
Validate before calling
const exists = await ResourceService.existsResource({ workspace: ws, path })
if (exists) {
const r = await ResourceService.getResource({ workspace: ws, path })
if (r.resource_type !== 'ai_agent') { sendUserToast('Path taken by another resource type', true); return }
} Type guard
function isFreeAgentPath(r: { resource_type: string } | undefined): boolean { return !r || r.resource_type === 'ai_agent' } Try / catch
try { await persist(path) } catch (e) { if (e.message.includes('already exists')) { sendUserToast(e.message, true); focusPathInput() } else { throw e } } Prevention
- Wait for the debounced path check to finish before enabling Save
- Suggest a suffixed path (e.g. my_agent_2) on collision
- Keep path availability checks server-authoritative at save time
When it happens
Trigger: ResourceService.existsResource returns true for `path`, and the fetched existing resource's resource_type differs from 'ai_agent' — the chosen path collides with, e.g., a variable, another resource kind, or a script path.
Common situations: User types a path already used by another resource; debounced availability check hadn't completed before Save was clicked; renaming an agent onto an existing non-agent path.
Related errors
- A resource was created at ${path} while this setup was runni
- The tool list for ${path} changed while it was loading. Try
- resource ${path} has no string "content" — is it an ${SKILLS
- A data table called ${name} was created while this setup was
- A variable was created at ${path} while this setup was runni
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/742250e8578df7ef.
Report an issue: GitHub.