windmill-labs/windmill · error
No endpoint mapping found for tool ${toolName}
Error message
No endpoint mapping found for tool ${toolName} What it means
createApiTools wraps chat function-calling tools for Windmill API endpoints. Each tool's executable fn looks up its method/path in an endpointMap keyed by tool name; this error is thrown when the fn runs for a tool name with no entry in that map. It is an internal consistency guard: tools are normally built from the same endpointTools list that populates the map, so a miss means the tool list and the map have diverged.
Source
Thrown at frontend/src/lib/components/copilot/chat/api/apiTools.ts:120
const endpoint = endpointMap[toolName]
const method = endpoint?.method?.toUpperCase() || 'GET'
// Determine if tool needs confirmation based on method
const needsConfirmation = ['DELETE', 'POST', 'PUT', 'PATCH'].includes(method)
return {
def: chatTool,
planModeSafe: !!endpoint && ['GET', 'HEAD', 'OPTIONS'].includes(method),
requiresConfirmation: needsConfirmation,
confirmationMessage: `Run ${toolName}`,
showDetails: true,
showFade: true,
fn: async ({ args, toolId, toolCallbacks }) => {
const toolName = chatTool.function.name
const endpoint = endpointMap[toolName]
if (!endpoint) {
throw new Error(`No endpoint mapping found for tool ${toolName}`)
}
try {
const workspace = get(workspaceStore) as string
let path = endpoint.path.replace('{workspace}', workspace)
// Build URL with path parameters
let url = `/api${path}`
const queryParams: Record<string, string> = {}
let requestBody: any = undefined
// Process arguments
for (const [key, value] of Object.entries(args)) {
if (key === 'body') {
requestBody = value
continue
}
View on GitHub (pinned to e474e8803c)
Solutions
- Build tool definitions with buildToolsFromEndpoints(endpointTools) and pass BOTH its tools and endpointMap into createApiTools so keys always match
- If constructing manually, add an entry endpointMap[tool.function.name] = { method, path } for every tool passed to createApiTools
- Log Object.keys(endpointMap) vs chatTools.map(t => t.function.name) to find the divergent tool name
- Assert the tool name against the map before invoking the tool fn (pre-check in the caller)
Example fix
// before
const { tools } = buildToolsFromEndpoints(endpointTools)
return createApiTools(customTools) // endpointMap defaults to {}
// after
const { tools, endpointMap } = buildToolsFromEndpoints(endpointTools)
return createApiTools([...customTools, ...tools], endpointMap) Defensive patterns
Strategy: validation
Validate before calling
const missing = chatTools.filter(t => !endpointMap[t.function.name])
if (missing.length) throw new Error(`Unmapped API tools: ${missing.map(t => t.function.name).join(', ')}`) Type guard
function hasEndpoint(name: string, map: Record<string, { method: string; path: string }>): boolean {
return Object.prototype.hasOwnProperty.call(map, name)
} Try / catch
try {
await tool.fn({ args, toolId, toolCallbacks })
} catch (e) {
if (e instanceof Error && e.message.startsWith('No endpoint mapping found for tool')) {
console.error(`API tool misconfigured: ${e.message}`)
return
}
throw e
} Prevention
- Always derive tools and endpointMap from the same buildToolsFromEndpoints call
- Never pass a hand-built chatTools list without a matching endpointMap
- Add a unit test asserting every tool name has an endpoint entry
When it happens
Trigger: Calling createApiTools(chatTools) with hand-built chatTools (or with the default endpointMap={}) so the returned tool fn executes for a name that was never registered via buildToolsFromEndpoints; also if a tool name is renamed/mutated after map construction.
Common situations: Developers wiring custom API tools into the copilot pass tool definitions without the matching endpoint map; loading API tools from a stale config where tool list and map were generated from different endpoint snapshots; tests constructing tools directly with an empty default map.
Related errors
- AI response was empty
- AI response contained empty code block
- AI response did not contain valid code. Please try rephrasin
- An unexpected error occurred. Please try again.
- No flow helpers found
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/7d94571d68af34c2.
Report an issue: GitHub.