{"record":{"id":"7ccd5aeaa96b677b","repo":"chinabugotech/hutool","slug":"model-service-is-not-of-type","errorCode":null,"errorMessage":"Model service is not of type: ","messagePattern":"Model service is not of type: ","errorType":"validation","errorClass":"AIException","httpStatus":null,"severity":"error","filePath":"hutool-ai/src/main/java/cn/hutool/ai/AIServiceFactory.java","lineNumber":77,"sourceCode":"\t/**\n\t * 获取AI服务\n\t *\n\t * @param config AIConfig配置\n\t * @param clazz AI服务类\n\t * @return clazz对应的AI服务类实例\n\t * @since 5.8.38\n\t * @param <T> AI服务类\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <T extends AIService> T getAIService(final AIConfig config, final Class<T> clazz) {\n\t\tfinal AIServiceProvider provider = providers.get(config.getModelName().toLowerCase());\n\t\tif (provider == null) {\n\t\t\tthrow new IllegalArgumentException(\"Unsupported model: \" + config.getModelName());\n\t\t}\n\n\t\tfinal AIService service = provider.create(config);\n\t\tif (!clazz.isInstance(service)) {\n\t\t\tthrow new AIException(\"Model service is not of type: \" + clazz.getSimpleName());\n\t\t}\n\n\t\treturn (T) service;\n\t}\n}\n","sourceCodeStart":59,"sourceCodeEnd":83,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-ai/src/main/java/cn/hutool/ai/AIServiceFactory.java#L59-L83","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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."],"exampleFix":"// before\nAIConfig cfg = new AIConfigBuilder(ModelName.OPENAI.getValue())\n    .setApiKey(k).build();\nGeminiService s = AIUtil.getAIService(cfg, GeminiService.class); // -> not of type: GeminiService\n\n// after\nGeminiService s = AIUtil.getGeminiService(\n    new AIConfigBuilder(ModelName.GEMINI.getValue()).setApiKey(k).build());","handlingStrategy":"validation","validationCode":"// Ensure config vendor matches the requested service interface\nString want = config.getModelName();\nif (!\"gemini\".equalsIgnoreCase(want) && !(config instanceof GeminiConfig)) {\n    throw new IllegalStateException(\n        \"config vendor \" + want + \" is not a GeminiConfig\");\n}\nGeminiService s = AIUtil.getGeminiService(config);","typeGuard":"// Narrow before calling the typed factory helper\nstatic boolean isOpenaiConfig(AIConfig c) {\n    return c != null && \"openai\".equalsIgnoreCase(c.getModelName());\n}","tryCatchPattern":"try {\n    return AIUtil.getAIService(config, GeminiService.class);\n} catch (AIException e) {\n    if (e.getMessage().startsWith(\"Model service is not of type\")) {\n        // mismatched config vendor vs requested interface -> rebuild config\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["type-mismatch","factory","configuration"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}