alibaba/spring-ai-alibaba · warning
未找到提供商 对应的工厂,使用默认的 OpenAI 工厂
Error message
未找到提供商 {} 对应的工厂,使用默认的 OpenAI 工厂 What it means
ChatClientFactoryDelegate looks up a ChatClientFactory by the model config's provider name. If no factory is registered for that provider, it warns and falls back to the OpenAI factory, translating the request to OpenAI-compatible semantics; if even the OpenAI factory is missing it throws UnsupportedOperationException.
Solutions
- Fix the provider string in the model config to exactly match a registered factory key (e.g. 'openai', 'dashscope')
- Add the missing provider module/dependency so its ChatClientFactory bean is registered
- Log or dump chatClientFactories.keySet() to see which providers are actually available
- Verify config normalization (toLowerCase/trim) matches how factories were registered
Example fix
// before provider: "DeepSeek-Chat" // not a registered provider key // after provider: "deepseek" // matches registered ChatClientFactory key
Defensive patterns
Strategy: validation
Validate before calling
Set<String> supported = Set.of("openai","dashscope","deepseek");
if (config.getProvider() == null || !supported.contains(config.getProvider().trim().toLowerCase()))
throw new IllegalArgumentException("unsupported provider: " + config.getProvider()); Type guard
boolean isSupportedProvider(String p) { return p != null && chatClientFactories.containsKey(p.trim().toLowerCase()); } Try / catch
try { client = delegate.createChatClient(config); }
catch (UnsupportedOperationException e) { log.error("provider not available: {}", config.getProvider(), e); throw e; } Prevention
- Copy provider names from the factory registry constants, not free text
- Include the starter module for each provider you configure
- Trim/lowercase provider strings before saving model configs
When it happens
Trigger: createChatClient is called with a ModelConfig whose provider string (lowercased) does not match any registered factory key — e.g. typo 'dashscope ' with whitespace, provider 'qwen' or 'deepseek' when the corresponding factory bean isn't on the classpath or not registered in chatClientFactories.
Common situations: Misspelled provider name in model config; provider-specific starter module not included as a dependency; provider constant mismatch after upgrade; extra whitespace/case differences in the config value.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- 不支持的模型提供商:
- 模型缺少 apiKey
- AppNotFound
- At least one fallback model must be specified
- At least one limit must be specified (threadLimit or…
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/4bebc50a4b8ff37c.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/service/client/ChatClientFactoryDelegate.java:98
log.debug("桥接服务中未找到模型配置 id={},尝试从 ModelConfigRepository 查找", modelConfigId);
config = modelConfigRepository.findById(modelConfigId);
}
if (config == null) {
throw new RuntimeException("模型配置不存在: " + modelConfigId);
}
if (config.getStatus() != 1) {
throw new RuntimeException("模型配置已禁用: " + modelConfigId);
}
String provider = config.getProvider().toLowerCase();
log.info("创建模型客户端,提供商: {}, 模型: {}", provider, config.getModelName());
ChatClientFactory factory = chatClientFactories.get(provider);
if (factory == null) {
// 如果找不到对应的 provider factory,默认使用 OpenAI
log.warn("未找到提供商 {} 对应的工厂,使用默认的 OpenAI 工厂", provider);
factory = chatClientFactories.get(OpenAiChatClientFactory.OPEN_AI_PROVIDER);
if (factory == null) {
throw new UnsupportedOperationException("不支持的模型提供商: " + config.getProvider() + ",且默认的 OpenAI 工厂也不可用");
}
}
ChatModel chatModel = factory.buildChatModel(config);
Map<String, Object> mergedParameters = mergeParameters(config, userParameters);
ChatOptions options = factory.buildChatOptions(config, mergedParameters, observationMetadata);
if (advisors != null) {
return ChatClient.builder(chatModel,observationRegistry,customObservationConvention,
new DefaultAdvisorObservationConvention()).defaultOptions(options).defaultAdvisors(advisors)
.build();
} else {
return ChatClient.builder(chatModel,observationRegistry,customObservationConvention
,new DefaultAdvisorObservationConvention()).defaultOptions(options).defaultAdvisors().build();
}View on GitHub (pinned to f82da0b50f)