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
- If you need Ollama model discovery, add an ollama branch to providerModelsUrl (and extractModels) — typically GET {baseUrl}/api/tags.
- At the call site, skip listProviderModels for protocols without discovery (ollama/azure/bedrock) and let the user type the model id.
- 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
- Skip listProviderModels for ollama/azure/bedrock — let the user type the model id.
- When adding a protocol to ConnectionTestProtocol, add the matching providerModelsUrl branch the same change.
- Validate protocol at the trust boundary (route input) against the discovery-capable set.
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
- invalid_generation
- xAI OAuth state mismatch: expected serverId=${XAI_PROVIDER_I
- invalid JSON in ${filePath}: ${message}
- ${filePath} must contain a JSON object
- ARTIFACT_MANIFEST_INVALID
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/d7c6b4c8b92f9021.
Report an issue: GitHub.