nexu-io/open-design · error · ConnectorServiceError

CONNECTOR_DISABLED

CONNECTOR_DISABLED

Error message

connector is disabled

What it means

Thrown by ConnectorService.connect() after the definition resolves and statusService.connect() reports status 'disabled'. A connector is disabled when its catalog definition sets disabled:true (e.g. administratively turned off or deprecated). ConnectorServiceError with code CONNECTOR_DISABLED and HTTP 403.

Source

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

    let auth: ComposioConnectionStart | undefined;
    let detailDefinition = definition;
    if (definition.authentication === 'composio' && options.credentials === undefined) {
      if (!options.callbackUrl) {
        throw new ConnectorServiceError('CONNECTOR_EXECUTION_FAILED', 'callbackUrl is required for Composio connectors', 400, { connectorId });
      }
      auth = await composioConnectorProvider.connect(definition, options.callbackUrl, options.signal);
      if (auth.kind === 'redirect_required' || auth.kind === 'pending') {
        return { connector: this.toDetail(detailDefinition), auth: publicComposioAuthStart(auth) };
      }
      if (auth.credentials !== undefined) {
        options = { ...options, ...(auth.accountLabel === undefined ? {} : { accountLabel: auth.accountLabel }), credentials: auth.credentials };
      }
    }

    const status = this.statusService.connect(detailDefinition, options.accountLabel, options.credentials);
    if (status.status === 'disabled') {
      throw new ConnectorServiceError('CONNECTOR_DISABLED', 'connector is disabled', 403);
    }
    return { connector: this.toDetail(detailDefinition), ...(auth === undefined ? {} : { auth: publicComposioAuthStart(auth) }) };
  }

  async disconnect(connectorId: string): Promise<ConnectorDetail> {
    const definition = this.getFastDefinition(connectorId) ?? await this.getDefinition(connectorId);
    if (!definition) {
      throw new ConnectorServiceError('CONNECTOR_NOT_FOUND', 'connector not found', 404);
    }
    if (definition.authentication === 'composio') {
      await composioConnectorProvider.disconnect(this.getCredential(connectorId)?.credentials);
    }
    this.statusService.disconnect(definition);
    return this.toDetail(definition);
  }

  async cancelPendingAuthorization(connectorId: string): Promise<ConnectorDetail> {
    const definition = this.getFastDefinition(connectorId) ?? await this.getDefinition(connectorId);

View on GitHub (pinned to 5be4028344)

Solutions

  1. Check definition.disabled / connector.status before offering the Connect action; hide disabled connectors in the picker.
  2. If the disable is unintended, update the catalog definition to set disabled:false.
  3. Offer the user an alternative connector that covers the same provider.
  4. Do not retry connect() on a disabled connector; the status will not change without a catalog edit.

Example fix

// before
await connectorService.connect(id, { callbackUrl });
// throws CONNECTOR_DISABLED

// after
const detail = await connectorService.getConnector(id);
if (detail.status === 'disabled') {
  throw new Error(`${detail.name} is disabled; choose another connector.`);
}
await connectorService.connect(id, { callbackUrl });
Defensive patterns

Strategy: type-guard

Validate before calling

async function connectIfEnabled(connectorService: ConnectorService, id: string, callbackUrl: string) {
  const detail = await connectorService.getConnector(id);
  if (detail.status === 'disabled') {
    throw new Error(`${detail.name} is disabled`);
  }
  return connectorService.connect(id, { callbackUrl });
}

Type guard

import type { ConnectorDetail } from './connectors/catalog.js';

function isEnabled(detail: ConnectorDetail): boolean {
  return detail.status !== 'disabled';
}

// const detail = await connectorService.getConnector(id);
// if (!isEnabled(detail)) return 'connector disabled';

Try / catch

try {
  return await connectorService.connect(id, { callbackUrl });
} catch (error) {
  if (error instanceof ConnectorServiceError && error.code === 'CONNECTOR_DISABLED') {
    return { ok: false, reason: 'disabled', connectorId: id };
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling connect() on a connector whose catalog definition is flagged disabled, e.g. a connector that was deprecated or turned off by an admin via the catalog.

Common situations: Catalog refresh marked a connector disabled; admin disabled a misbehaving integration; deprecated connector still referenced by old UI state.

Related errors


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