{"record":{"id":"eb35aa4e7c3b564b","repo":"alibaba/nacos","slug":"invalid-param-eb35aa","errorCode":"INVALID_PARAM","errorMessage":"Configuration cannot be null","messagePattern":"Configuration cannot be null","errorType":"validation","errorClass":"NacosException","httpStatus":null,"severity":"warning","filePath":"console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleCopilotConfigController.java","lineNumber":127,"sourceCode":"    }\n    \n    /**\n     * Create or update Copilot configuration. Only accepts apiKey, model, studioUrl and studioProject fields, other\n     * fields use defaults.\n     *\n     * @param request HTTP servlet request.\n     * @param config Simplified CopilotProperties with only apiKey, model, studioUrl and studioProject\n     * @return success result\n     */\n    @Since(\"3.2.0\")\n    @PostMapping\n    @Secured(resource = CONSOLE_RESOURCE_NAME_PREFIX + \"copilot/config\",\n        action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> saveConfig(HttpServletRequest request,\n        @RequestBody CopilotProperties config)\n        throws NacosException {\n        if (config == null) {\n            throw new NacosException(NacosException.INVALID_PARAM, \"Configuration cannot be null\");\n        }\n        \n        // Get existing config to preserve other fields, or create new one with defaults\n        CopilotProperties existingConfig = getStoredConfig();\n        CopilotProperties fullConfig;\n        \n        if (existingConfig != null) {\n            // Use existing config and only update apiKey, model, studioUrl and studioProject\n            fullConfig = existingConfig;\n        } else {\n            // Create new config with default values\n            fullConfig = new CopilotProperties();\n        }\n        \n        // Update only apiKey, model, studioUrl and studioProject\n        if (config.getApiKey() != null) {\n            fullConfig.setApiKey(config.getApiKey());\n        }","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleCopilotConfigController.java#L109-L145","documentation":"Thrown by ConsoleCopilotConfigController.saveConfig (POST /v3/console/.../copilot/config, @Since 3.2.0) when the request carries no JSON body, so the @RequestBody CopilotProperties parameter binds to null. It uses NacosException.INVALID_PARAM (HTTP 400). The controller intentionally requires a body because it merges the submitted apiKey/model/studioUrl/studioProject onto the stored CopilotProperties.","triggerScenarios":"POSTing to the copilot config endpoint with an empty body, a wrong Content-Type (not application/json), or a literal JSON null. The @RequestBody parameter resolves to null and the guard at line 127 fires.","commonSituations":"Console UI or automation sending a save-config request without serializing the form; curl without -d; a proxy stripping the body or Content-Type header; an integration test that posts an empty entity.","solutions":["Send a JSON object in the request body with Content-Type: application/json; an empty object '{}' is accepted.","If using a typed client, make sure the CopilotProperties payload object is constructed and serialized rather than passed as null.","Verify no intermediary (gateway/RestTemplate) is dropping the body or the Content-Type header before it reaches the controller.","Check the HTTP request on the client side to confirm the body is actually transmitted before calling the API."],"exampleFix":"// before\nPOST /v3/console/ai/copilot/config\nContent-Type: application/json\n\n// after\nPOST /v3/console/ai/copilot/config\nContent-Type: application/json\n\n{}","handlingStrategy":"validation","validationCode":"// Ensure a non-null body is sent before calling saveConfig\nCopilotProperties body = new CopilotProperties();\nif (body == null) {\n    throw new IllegalArgumentException(\"Copilot config body must not be null\");\n}\nrestTemplate.postForObject(copilotConfigUrl, body, Result.class);","typeGuard":"// Java: guard that a serializable body exists before the call\nboolean hasConfigBody = body != null;\nif (!hasConfigBody) { /* do not call the API */ }","tryCatchPattern":"try {\n    saveConfig(request, body);\n} catch (NacosException e) {\n    if (e.getErrCode() == NacosException.INVALID_PARAM) {\n        // body was null/missing; fix the request payload\n    } else { throw e; }\n}","preventionTips":["Always send Content-Type: application/json with a JSON object body for this POST.","Unit-test the client with a non-null payload and assert the request entity has a body.","Validate the payload object is non-null in your service layer before the HTTP call."],"tags":["validation","console","copilot","ai","api"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}