{"record":{"id":"14cf6451e807bc3d","repo":"OtterMind/Chat2DB","slug":"provider-is-required","errorCode":null,"errorMessage":"provider is required","messagePattern":"provider is required","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiModelConfigServiceImpl.java","lineNumber":358,"sourceCode":"            runtimeModel.setBaseUrl(defaultValue(trimToNull(runtimeModel.getBaseUrl()), trimToNull(System.getenv(\"MINIMAX_BASE_URL\"))));\n            runtimeModel.setBaseUrl(defaultValue(trimToNull(runtimeModel.getBaseUrl()), DEFAULT_MINIMAX_BASE_URL));\n            return;\n        }\n        if (provider == AiProviderEnum.CLAUDE) {\n            runtimeModel.setApiKey(defaultValue(trimToNull(runtimeModel.getApiKey()), trimToNull(System.getenv(\"ANTHROPIC_API_KEY\"))));\n            runtimeModel.setBaseUrl(defaultValue(trimToNull(runtimeModel.getBaseUrl()), trimToNull(System.getenv(\"ANTHROPIC_BASE_URL\"))));\n            return;\n        }\n        if (provider == AiProviderEnum.GEMINI) {\n            runtimeModel.setProjectId(defaultValue(trimToNull(runtimeModel.getProjectId()), trimToNull(System.getenv(\"GOOGLE_CLOUD_PROJECT\"))));\n            runtimeModel.setLocation(defaultValue(trimToNull(runtimeModel.getLocation()), trimToNull(System.getenv(\"GOOGLE_CLOUD_LOCATION\"))));\n            runtimeModel.setLocation(defaultValue(runtimeModel.getLocation(), DEFAULT_GEMINI_LOCATION));\n        }\n    }\n\n    private void validateRuntimeModel(AiRuntimeModel runtimeModel) {\n        if (Objects.isNull(runtimeModel.getProvider())) {\n            throw new IllegalArgumentException(\"provider is required\");\n        }\n        if (StringUtils.isBlank(runtimeModel.getModel())) {\n            throw new IllegalArgumentException(\"model is required\");\n        }\n        AiProviderEnum provider = AiProviderEnum.from(runtimeModel.getProvider());\n        if (provider == null) {\n            throw new IllegalArgumentException(\"Unsupported provider: \" + runtimeModel.getProvider());\n        }\n        if (provider == AiProviderEnum.OPENAI || provider == AiProviderEnum.CLAUDE) {\n            return;\n        }\n        if (provider == AiProviderEnum.GEMINI) {\n        }\n    }\n\n\n    private synchronized void loadFromDisk() {\n        if (!Files.exists(storagePath)) {","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiModelConfigServiceImpl.java#L340-L376","documentation":"Thrown as IllegalArgumentException('provider is required') by AiModelConfigServiceImpl.validateRuntimeModel when runtimeModel.getProvider() is null. This is a raw IllegalArgumentException, not a BusinessException, so it bypasses the i18n BusinessException handler. It indicates the resolved AiRuntimeModel was constructed without a provider.","triggerScenarios":"validateRuntimeModel receives an AiRuntimeModel whose provider is null. Reachable when resolveRuntimeModel built a runtimeModel from a config/request that left provider null after defaultValue merging, or when validateRuntimeModel is called directly with an incomplete model.","commonSituations":"A saved AiModelConfig has a null provider (corrupt or hand-built config); the resolve request and the base config both lacked a provider so defaultValue(null,null)=null; programmatic construction of AiRuntimeModel without setting provider.","solutions":["Ensure the saved model config (or the resolve request) has a non-null provider (OPENAI, CLAUDE, GEMINI, or MINIMAX).","Audit the AiModelConfig record that produced the null provider and fix its provider field.","Guard resolveRuntimeModel to fail with a clearer BusinessException before reaching validateRuntimeModel."],"exampleFix":"// before: config saved with null provider\nAiModelConfig cfg = new AiModelConfig();\ncfg.setModel(\"gpt-4o\"); cfg.setApiKey(key); // provider missing\nconfigService.save(cfg);\n\n// after\nAiModelConfig cfg = new AiModelConfig();\ncfg.setProvider(AiProviderEnum.OPENAI.name());\ncfg.setModel(\"gpt-4o\"); cfg.setApiKey(key);\nconfigService.save(cfg);","handlingStrategy":"validation","validationCode":"AiRuntimeModel m = /* built */;\nif (m.getProvider() == null) {\n    throw new IllegalArgumentException(\"provider is required before validate\");\n}","typeGuard":"static boolean hasProvider(AiRuntimeModel m) {\n    return m != null && m.getProvider() != null;\n}","tryCatchPattern":"try {\n    service.validateRuntimeModel(m);\n} catch (IllegalArgumentException e) {\n    if (\"provider is required\".equals(e.getMessage())) {\n        return ResponseEntity.badRequest().body(\"set a provider (OPENAI/CLAUDE/GEMINI/MINIMAX)\");\n    }\n    throw e;\n}","preventionTips":["Always set provider when building or saving an AiModelConfig/AiRuntimeModel.","Validate provider presence before persisting a config.","Treat a null provider in a saved config as corrupt data and fix it."],"tags":["ai","model-config","validation","illegal-argument"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}