nexu-io/open-design · error · ConnectorServiceError
CONNECTOR_TOOL_NOT_FOUND
CONNECTOR_TOOL_NOT_FOUND
Error message
connector tool is not allowed
What it means
Thrown by ConnectorService.execute() with HTTP 404 when request.toolName is not present in definition.allowedToolNames — the catalog whitelist for that connector. This is checked after the connection gate but before the per-tool lookup, so the connector is reachable but the tool is not enabled for it. details includes connectorId and toolName.
Source
Thrown at apps/daemon/src/connectors/service.ts:784
const connector = this.toDetail(definition);
if (connector.status === 'disabled') {
throw new ConnectorServiceError('CONNECTOR_DISABLED', 'connector is disabled', 403);
}
if (connector.status !== 'connected') {
throw new ConnectorServiceError('CONNECTOR_NOT_CONNECTED', 'connector is not connected', 403, {
connectorId: request.connectorId,
status: connector.status,
});
}
if (request.expectedAccountLabel !== undefined && connector.accountLabel !== request.expectedAccountLabel) {
throw new ConnectorServiceError('CONNECTOR_NOT_CONNECTED', 'connector account changed since refresh approval', 409, {
connectorId: request.connectorId,
expectedAccountLabel: request.expectedAccountLabel,
currentAccountLabel: connector.accountLabel ?? null,
});
}
if (!definition.allowedToolNames.includes(request.toolName)) {
throw new ConnectorServiceError('CONNECTOR_TOOL_NOT_FOUND', 'connector tool is not allowed', 404, {
connectorId: request.connectorId,
toolName: request.toolName,
});
}
const tool = definition.tools.find((candidate) => candidate.name === request.toolName);
if (!tool) {
throw new ConnectorServiceError('CONNECTOR_TOOL_NOT_FOUND', 'connector tool not found', 404);
}
const runtimeSafety = runtimeSafetyForTool(tool);
const effectiveApproval = stricterApproval(stricterApproval(definition.minimumApproval, tool.safety.approval), runtimeSafety.approval);
if (effectiveApproval !== 'auto' || runtimeSafety.sideEffect !== 'read') {
throw new ConnectorServiceError('CONNECTOR_SAFETY_DENIED', 'connector tool is not auto-approved read-only by current safety policy', 403, {
connectorId: request.connectorId,
toolName: request.toolName,
approvalPolicy: effectiveApproval ?? null,
safety: { ...runtimeSafety },
});
}View on GitHub (pinned to 5be4028344)
Solutions
- List the connector's allowed tools (connectorService list / od connector tools) and call one of those names instead.
- If the tool should be allowed, update the connector catalog definition to include it in allowedToolNames before retrying.
- Check for typos / casing — toolName must match exactly (the lookup is case-sensitive).
Example fix
// before: guessing a tool name
await execute({ connectorId, toolName: 'gmail_send', input }, ctx);
// after: pick from the live allowed list
const allowed = connectorService.getAllowedToolNames(connectorId);
const toolName = allowed.find(t => t.startsWith('gmail'));
if (!toolName) throw new Error('no gmail tool available');
await execute({ connectorId, toolName, input }, ctx); Defensive patterns
Strategy: validation
Validate before calling
const def = connectorService.getDefinition(request.connectorId);
if (!def?.allowedToolNames.includes(request.toolName)) {
throw new Error(`tool ${request.toolName} not allowed for ${request.connectorId}`);
}
await connectorService.execute(request, context); Type guard
function isAllowedTool(def: ConnectorCatalogDefinition | undefined, name: string): boolean {
return !!def && def.allowedToolNames.includes(name);
} Try / catch
try { await connectorService.execute(request, context); }
catch (e) {
if (e instanceof ConnectorServiceError && e.code === 'CONNECTOR_TOOL_NOT_FOUND' && e.status === 404) {
// fetch allowedToolNames, pick a substitute, or surface 'tool unavailable' to the agent
} else throw e;
} Prevention
- Expose the connector's allowedToolNames to the agent so it only proposes valid tools.
- Refresh the catalog after connector updates so stale tool names are not retained.
- Validate toolName against the live catalog at the request boundary.
When it happens
Trigger: Calling execute() with a toolName that the connector's catalog definition does not allow — either a typo, a tool removed from the connector manifest, or a connector whose allowedToolNames was pruned by admin policy.
Common situations: Agent hallucinated a tool name; the connector catalog was refreshed and the tool was dropped from allowedToolNames; an environment-specific manifest restricts which tools a connector exposes.
Related errors
- CONNECTOR_NOT_FOUND
- CONNECTOR_DISABLED
- connector refresh source requires connector metadata
- unknown model: ${model}. Pass --model from the registered li
- model "${model}" is not registered for surface "${where}". A
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/9e5b36b338f60cfc.
Report an issue: GitHub.