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

  1. Fix the provider string in the model config to exactly match a registered factory key (e.g. 'openai', 'dashscope')
  2. Add the missing provider module/dependency so its ChatClientFactory bean is registered
  3. Log or dump chatClientFactories.keySet() to see which providers are actually available
  4. 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

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


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)