chinabugotech/hutool · error · AIException
Model service is not of type:
Error message
Model service is not of type:
What it means
Thrown when the provider registered for config.getModelName() creates an AIService whose runtime type is not assignable to the clazz argument passed to getAIService(config, clazz). The factory looks up the provider by vendor name, calls provider.create(config), then asserts clazz.isInstance(service). A mismatch means the config was built for one vendor but a different vendor's service interface was requested.
Source
Thrown at hutool-ai/src/main/java/cn/hutool/ai/AIServiceFactory.java:77
/**
* 获取AI服务
*
* @param config AIConfig配置
* @param clazz AI服务类
* @return clazz对应的AI服务类实例
* @since 5.8.38
* @param <T> AI服务类
*/
@SuppressWarnings("unchecked")
public static <T extends AIService> T getAIService(final AIConfig config, final Class<T> clazz) {
final AIServiceProvider provider = providers.get(config.getModelName().toLowerCase());
if (provider == null) {
throw new IllegalArgumentException("Unsupported model: " + config.getModelName());
}
final AIService service = provider.create(config);
if (!clazz.isInstance(service)) {
throw new AIException("Model service is not of type: " + clazz.getSimpleName());
}
return (T) service;
}
}
View on GitHub (pinned to 8870454b2a)
Solutions
- Pair the config vendor with the matching service interface (OpenaiConfig->OpenaiService, GeminiConfig->GeminiService).
- Prefer the typed AIUtil helpers (getOpenAIService, getGeminiService, getDeepSeekService, ...) which pair config and interface correctly.
- If using a custom AIServiceProvider, ensure create() returns an instance of the interface callers will request.
- Build the config via AIConfigBuilder(ModelName.X.getValue()) so the vendor string and the requested interface stay consistent.
Example fix
// before
AIConfig cfg = new AIConfigBuilder(ModelName.OPENAI.getValue())
.setApiKey(k).build();
GeminiService s = AIUtil.getAIService(cfg, GeminiService.class); // -> not of type: GeminiService
// after
GeminiService s = AIUtil.getGeminiService(
new AIConfigBuilder(ModelName.GEMINI.getValue()).setApiKey(k).build()); Defensive patterns
Strategy: validation
Validate before calling
// Ensure config vendor matches the requested service interface
String want = config.getModelName();
if (!"gemini".equalsIgnoreCase(want) && !(config instanceof GeminiConfig)) {
throw new IllegalStateException(
"config vendor " + want + " is not a GeminiConfig");
}
GeminiService s = AIUtil.getGeminiService(config); Type guard
// Narrow before calling the typed factory helper
static boolean isOpenaiConfig(AIConfig c) {
return c != null && "openai".equalsIgnoreCase(c.getModelName());
} Try / catch
try {
return AIUtil.getAIService(config, GeminiService.class);
} catch (AIException e) {
if (e.getMessage().startsWith("Model service is not of type")) {
// mismatched config vendor vs requested interface -> rebuild config
}
throw e;
} Prevention
- Use the typed AIUtil.getXxxService helpers instead of the generic overload.
- Keep a single source mapping from ModelName to its service interface.
- Unit-test each config/service pair at app startup.
When it happens
Trigger: Mixing vendor config with the wrong service interface: e.g. building an OpenaiConfig then calling AIUtil.getAIService(config, GeminiService.class); or calling AIUtil.getDeepSeekService(config) on a config built with AIConfigBuilder("gemini"). Also when a custom provider returns the wrong AIService subtype from create().
Common situations: Copy-paste errors wiring config to service; using the generic AIUtil.getAIService(config, clazz) overload instead of the typed helpers; refactoring that changes the vendor string in AIConfigBuilder without updating the requested service class.
Related errors
- Unsupported model:
- Unsupported model:
- alphabet must contain at least %d unique characters: %d
- alphabet must not contain spaces: index %d
- Default value [{}]({}) is not the instance of [{}]
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/7ccd5aeaa96b677b.
Report an issue: GitHub.