nexu-io/open-design · error · ConnectorServiceError

CONNECTOR_NOT_FOUND

CONNECTOR_NOT_FOUND

Error message

connector not found

What it means

Thrown by ConnectorService.getConnector() when getDefinition(connectorId) resolves to undefined, i.e. no catalog entry matches the id. It is a ConnectorServiceError with code CONNECTOR_NOT_FOUND and HTTP 404. This is the read path behind the GET connector detail route and the 'od connector get' CLI.

Source

Thrown at apps/daemon/src/connectors/service.ts:640

    if (options.refresh) composioConnectorProvider.clearDiscoveryCache();
    const definitions = options.refresh && !options.hydrateTools
      ? await composioConnectorProvider.refreshCatalog(options.signal)
      : options.hydrateTools
        ? await this.listHydratedDefinitions(options.signal)
        : await this.listDefinitions(options.signal);
    return {
      connectors: definitions.map((definition) => this.toDetail(definition)),
      meta: {
        provider: 'composio',
        ...(options.refresh ? { refreshRequested: true } : {}),
      },
    };
  }

  async getConnector(connectorId: string, signal?: AbortSignal): Promise<ConnectorDetail> {
    const definition = await this.getDefinition(connectorId, signal);
    if (!definition) {
      throw new ConnectorServiceError('CONNECTOR_NOT_FOUND', 'connector not found', 404);
    }
    return this.toDetail(definition);
  }

  async getHydratedConnector(connectorId: string, signal?: AbortSignal): Promise<ConnectorDetail> {
    const definition = await this.getHydratedDefinition(connectorId, signal);
    if (!definition) {
      throw new ConnectorServiceError('CONNECTOR_NOT_FOUND', 'connector not found', 404);
    }
    return this.toDetail(definition);
  }

  async getPreviewConnector(connectorId: string, options: { toolsLimit: number; toolsCursor?: string; signal?: AbortSignal }): Promise<ConnectorDetail> {
    const definition = await this.getPreviewDefinition(connectorId, options);
    if (!definition) {
      throw new ConnectorServiceError('CONNECTOR_NOT_FOUND', 'connector not found', 404);
    }
    return this.toDetail(definition);

View on GitHub (pinned to 5be4028344)

Solutions

  1. List connectors first (listConnectors) and copy the exact id from the catalog.
  2. Pass { refresh: true } to listConnectors to force a Composio catalog refresh, then retry getConnector.
  3. Verify the connector is not disabled/removed upstream in the Composio dashboard.
  4. Normalize the id (trim, lowercase only if the catalog uses lowercase ids) before the call.

Example fix

// before
await connectorService.getConnector('Gihub');  // typo
// throws CONNECTOR_NOT_FOUND

// after
const { connectors } = await connectorService.listConnectors({ refresh: true });
const id = connectors.find((c) => c.name.toLowerCase().includes('github'))?.id;
if (!id) throw new Error('github connector unavailable');
await connectorService.getConnector(id);
Defensive patterns

Strategy: validation

Validate before calling

async function resolveConnectorId(connectorService: ConnectorService, candidate: string): Promise<string | null> {
  const { connectors } = await connectorService.listConnectors();
  const found = connectors.find((c) => c.id === candidate);
  return found ? found.id : null;
}

const id = await resolveConnectorId(connectorService, rawId);
if (!id) throw new Error(`unknown connector: ${rawId}`);
await connectorService.getConnector(id);

Type guard

async function connectorExists(connectorService: ConnectorService, id: string): Promise<boolean> {
  const { connectors } = await connectorService.listConnectors();
  return connectors.some((c) => c.id === id);
}

// if (!(await connectorExists(connectorService, id))) return 'connector not available';

Try / catch

try {
  return await connectorService.getConnector(id);
} catch (error) {
  if (error instanceof ConnectorServiceError && error.code === 'CONNECTOR_NOT_FOUND') {
    await connectorService.listConnectors({ refresh: true });
    return connectorService.getConnector(id); // one retry after refresh
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling getConnector(connectorId) with an id that is not present in the local fast catalog nor returned by Composio after a refresh, e.g. a typo, a stale id from an older catalog, or an id from a different environment.

Common situations: Hard-coded connector id drifted after a catalog refresh; user typed/pasted an id; the Composio catalog failed to load and only the static catalog is available; cross-environment id mismatch (beta vs stable).

Related errors


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