decolua/9router · error
Unknown provider: ${providerInput}
Error message
Unknown provider: ${providerInput} What it means
handleSingleProviderFetch resolves the incoming provider/model string via resolveProviderId() and looks it up in the AI_PROVIDERS registry. If no provider matches, it returns HTTP 400 'Unknown provider: <input>'. Unlike chat, provider IS the model here, so an unknown model alias also lands here.
Source
Thrown at src/sse/handlers/fetch.js:120
log,
comboName: providerInput,
comboStrategy,
comboStickyLimit
});
}
return handleSingleProviderFetch(body, providerInput, request, apiKey, settings);
}
async function handleSingleProviderFetch(body, providerInput, request, apiKey, settings) {
const targetUrl = body.url;
const format = body.format;
const maxCharacters = body.max_characters;
const providerId = resolveProviderId(providerInput);
const resolvedProvider = AI_PROVIDERS[providerId];
if (!resolvedProvider) {
log.warn("FETCH", "Unknown provider", { provider: providerInput });
return errorResponse(HTTP_STATUS.BAD_REQUEST, `Unknown provider: ${providerInput}`);
}
const providerConfig = resolvedProvider.fetchConfig;
if (!providerConfig) {
log.warn("FETCH", "Provider does not support web fetch", { provider: providerId });
return errorResponse(HTTP_STATUS.BAD_REQUEST, `Provider ${providerId} does not support web fetch`);
}
if (providerInput !== providerId) {
log.info("ROUTING", `${providerInput} → ${providerId}`);
} else {
log.info("ROUTING", `Provider: ${providerId}`);
}
// No-auth fetch path (kept for parity though no current fetch provider sets noAuth)
if (resolvedProvider.noAuth) {
log.info("AUTH", `\x1b[32m${providerId} no-auth mode\x1b[0m`);View on GitHub (pinned to 90b52e06ff)
Solutions
- Check the spelling against the provider list shown in the 9Router dashboard providers page
- Use the exact provider/model id as registered in open-sse/providers/registry (resolveProviderId handles case/alias, but not arbitrary names)
- If the provider exists for chat but not fetch, verify it has a fetchConfig in the registry - only fetch-capable providers resolve here
- Update the client's model list after upgrading 9Router (registry changes between versions)
Example fix
// before
{ model: 'jina reader' }
// after
{ model: 'jina' } // exact registered provider id Defensive patterns
Strategy: validation
Validate before calling
async function assertKnownFetchProvider(model) {
const res = await fetch(`${baseUrl}/dashboard/api/providers`);
const known = new Set((await res.json()).map((p) => p.id));
if (!known.has(model)) throw new Error(`Unknown provider for fetch: ${model}`);
} Type guard
function isRegisteredProvider(model, registryIds) {
return typeof model === 'string' && registryIds.includes(model.trim().toLowerCase());
} Try / catch
const res = await fetch(endpoint, { method: 'POST', body: JSON.stringify({ model, url }) });
if (res.status === 400) {
const msg = await res.text();
if (msg.startsWith('Unknown provider:')) {
console.error(`Provider '${model}' not in registry - check dashboard provider list`);
}
} Prevention
- Keep the client's model list in sync with the 9Router registry (export from the dashboard)
- Trim and normalize provider names before sending; resolveProviderId handles case but not stray whitespace
- After upgrading 9Router, re-check that provider ids used by automation still exist
- Remember: the fetch endpoint requires fetch-capable providers; a chat-only name may still fail downstream
When it happens
Trigger: POSTing {model:'gpt-4o'} when no such fetch-capable provider/model is registered; typos ('jinia', 'Jina ' with trailing space); a provider name that exists for chat but not for fetch; stale client config after a provider was renamed or removed from the registry.
Common situations: Copying a model name from chat code into the fetch endpoint; using a provider alias removed in an upgrade; environment where the provider registry differs from the client's hardcoded list; sending a combo name that was deleted from the dashboard.
Related errors
- Provider ${providerId} does not support web fetch
- Missing required field: url
- Invalid URL format
- err.message (SSRF guard: blocked internal/private/metadata U
- Unknown provider: ${providerInput}
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/1ed560582b7fdfdd.
Report an issue: GitHub.