nexu-io/open-design · error · Error

Unsupported protocol: ${protocol}

Error message

Unsupported protocol: ${protocol}

What it means

Thrown by providerModelsUrl() when the protocol is not one of aihubmix/openai/senseaudio/anthropic/google. The ConnectionTestProtocol union also contains ollama, azure and bedrock; azure and bedrock are short-circuited earlier in listProviderModels (returning unsupported_protocol / a synthetic success), so in practice ollama (and any future protocol) reaches this throw because model discovery has no URL builder for it.

Source

Thrown at apps/daemon/src/integrations/provider-models.ts:255

function providerModelsUrl(protocol: ConnectionTestProtocol, baseUrl: string, apiKey: string): string {
  if (protocol === 'aihubmix') {
    // AIHubMix exposes its chat catalogue on a dedicated endpoint
    // (GET /api/v1/models?type=llm), not the OpenAI /v1/models route.
    return aihubmixCatalogUrl(baseUrl, 'llm');
  }
  if (protocol === 'openai' || protocol === 'senseaudio') {
    return appendVersionedApiPath(baseUrl, '/models');
  }
  if (protocol === 'anthropic') {
    const url = new URL(appendVersionedApiPath(baseUrl, '/models'));
    url.searchParams.set('limit', '1000');
    return url.toString();
  }
  if (protocol === 'google') {
    return googleProviderModelsUrl(baseUrl, apiKey);
  }
  throw new Error(`Unsupported protocol: ${protocol}`);
}

function providerModelsHeaders(
  protocol: ConnectionTestProtocol,
  apiKey: string,
): Record<string, string> {
  if (protocol === 'openai' || protocol === 'senseaudio') {
    return { authorization: `Bearer ${apiKey}` };
  }
  if (protocol === 'aihubmix') {
    // The catalogue is public — only attach Bearer auth (+ APP-Code) when the
    // user actually supplied a key. An empty `Bearer ` would be rejected by
    // some gateways, so send no headers when the key is blank.
    return apiKey.trim() ? aihubmixHeaders(apiKey) : {};
  }
  if (protocol === 'anthropic') {
    return {
      'x-api-key': apiKey,

View on GitHub (pinned to 5be4028344)

Solutions

  1. If you need Ollama model discovery, add an ollama branch to providerModelsUrl (and extractModels) — typically GET {baseUrl}/api/tags.
  2. At the call site, skip listProviderModels for protocols without discovery (ollama/azure/bedrock) and let the user type the model id.
  3. Guard the input: validate protocol against the supported discovery set before calling.

Example fix

// before
if (protocol === 'google') return googleProviderModelsUrl(baseUrl, apiKey);
throw new Error(`Unsupported protocol: ${protocol}`);

// after
if (protocol === 'google') return googleProviderModelsUrl(baseUrl, apiKey);
if (protocol === 'ollama') return new URL('/api/tags', baseUrl).toString();
throw new Error(`Unsupported protocol: ${protocol}`);
Defensive patterns

Strategy: validation

Validate before calling

import type { ConnectionTestProtocol } from '@open-design/contracts';

const DISCOVERY_SUPPORTED: ReadonlySet<ConnectionTestProtocol> = new Set([
  'openai', 'senseaudio', 'anthropic', 'google', 'aihubmix',
]);

function supportsModelDiscovery(protocol: ConnectionTestProtocol): boolean {
  return DISCOVERY_SUPPORTED.has(protocol);
}

// usage
if (!supportsModelDiscovery(input.protocol)) {
  return { models: [], reason: 'no_discovery' };
}

Type guard

function isDiscoverableProtocol(p: string): p is 'openai' | 'senseaudio' | 'anthropic' | 'google' | 'aihubmix' {
  return p === 'openai' || p === 'senseaudio' || p === 'anthropic' || p === 'google' || p === 'aihubmix';
}

Try / catch

try {
  return await listProviderModels(input);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unsupported protocol:')) {
    return { models: [], reason: 'no_discovery' };
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling listProviderModels({ protocol: 'ollama', ... }) (ollama is in the union but has no models-URL branch), or passing a protocol value the function does not recognise. azure/bedrock do NOT reach this throw because listProviderModels returns before calling providerModelsUrl.

Common situations: User adds an Ollama provider and the model picker tries to enumerate models; a new protocol is added to ConnectionTestProtocol without a corresponding branch here; a caller forwards an unvalidated protocol string.

Related errors


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