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

  1. List the connector's allowed tools (connectorService list / od connector tools) and call one of those names instead.
  2. If the tool should be allowed, update the connector catalog definition to include it in allowedToolNames before retrying.
  3. 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

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


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/9e5b36b338f60cfc. Report an issue: GitHub.