ruvnet/ruflo · error
Unknown provider: ${config.provider}
Error message
Unknown provider: ${config.provider} What it means
ProviderManager.createProvider() switches on config.provider and only recognizes 'anthropic', 'openai', 'google', 'cohere', 'ollama' and 'ruvector'; every other value falls through to a default that throws a plain Error. The comparison is case-sensitive.
Source
Thrown at v3/@claude-flow/providers/src/provider-manager.ts:131
config,
logger: this.logger,
};
switch (config.provider) {
case 'anthropic':
return new AnthropicProvider(options);
case 'openai':
return new OpenAIProvider(options);
case 'google':
return new GoogleProvider(options);
case 'cohere':
return new CohereProvider(options);
case 'ollama':
return new OllamaProvider(options);
case 'ruvector':
return new RuVectorProvider(options);
default:
throw new Error(`Unknown provider: ${config.provider}`);
}
}
/**
* Complete a request with automatic provider selection
*/
async complete(request: LLMRequest, preferredProvider?: LLMProvider): Promise<LLMResponse> {
// Check cache first
if (this.config.cache?.enabled) {
const cached = this.getCached(request);
if (cached) {
this.logger.debug('Cache hit', { requestId: request.requestId });
return cached;
}
}
// Select provider
const provider = preferredProviderView on GitHub (pinned to fa13ee4ad6)
Solutions
- Use one of the exact case-sensitive ids: anthropic | openai | google | cohere | ollama | ruvector
- Normalize the value at config load: trim() + toLowerCase() before it reaches the manager
- After initialize(), check manager.getProvider(id) returned a provider - initialization failures are logged, not thrown, so a typo silently yields a missing provider
- For unsupported vendors, instantiate the provider class yourself and pass it as preferredProvider to manager.complete()
Example fix
// before
providers: [{ provider: 'OpenAI' as any, apiKey, model: 'gpt-4o' }] // capital O -> Unknown provider
// after
providers: [{ provider: 'openai', apiKey, model: 'gpt-4o' }] // exact registry id Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED_PROVIDERS = ['anthropic', 'openai', 'google', 'cohere', 'ollama', 'ruvector'] as const;
for (const p of managerConfig.providers) {
if (!SUPPORTED_PROVIDERS.includes(p.provider as never)) {
throw new Error(
`Unsupported provider '${p.provider}'. Supported: ${SUPPORTED_PROVIDERS.join(', ')}`
);
}
}
await manager.initialize(); Type guard
const SUPPORTED_PROVIDERS = ['anthropic', 'openai', 'google', 'cohere', 'ollama', 'ruvector'] as const;
type SupportedProviderId = (typeof SUPPORTED_PROVIDERS)[number];
function isSupportedProvider(v: unknown): v is SupportedProviderId {
return typeof v === 'string' && (SUPPORTED_PROVIDERS as readonly string[]).includes(v.trim().toLowerCase())
? true
: false;
} Prevention
- Whitelist provider ids against the factory's known set before calling initialize()
- Normalize env-supplied provider ids: trim() and toLowerCase() at config load
- After initialize(), assert manager.getProvider(id) exists - createProvider failures are logged and skipped, not thrown
When it happens
Trigger: A ProviderManagerConfig whose providers[] entry has provider: 'azure-openai', 'groq', 'mistral', 'bedrock', or a case variant like 'OpenAI' - initialize() then fails (the manager logs 'Failed to initialize ...' and skips that provider, leaving it absent from the registry).
Common situations: Provider id from an env var with different casing/whitespace; config authored for a newer version supporting more vendors; copy-pasted example using an alias; trailing whitespace after JSON/YAML edit.
Related errors
- Model is required for ${this.name} provider
- localCompute: no adapter for graphId=${input.graphId}
- RuvllmConfig.modelsDir is required
- Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}
- Dangerous key segment rejected: ${part}
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/0cdd8cbc5cf0026c.
Report an issue: GitHub.