{"record":{"id":"23f5992e2c85a9b1","repo":"spring-projects/spring-ai","slug":"clients-must-not-be-empty-23f599","errorCode":null,"errorMessage":"clients must not be empty","messagePattern":"clients must not be empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/sampling/SyncSamplingSpecification.java","lineNumber":32,"sourceCode":" * limitations under the License.\n */\n\npackage org.springframework.ai.mcp.annotation.method.sampling;\n\nimport java.util.Arrays;\nimport java.util.Objects;\nimport java.util.function.Function;\n\nimport io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;\nimport io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;\n\npublic record SyncSamplingSpecification(String[] clients,\n\t\tFunction<CreateMessageRequest, CreateMessageResult> samplingHandler) {\n\n\tpublic SyncSamplingSpecification {\n\t\tObjects.requireNonNull(clients, \"clients must not be null\");\n\t\tif (clients.length == 0 || Arrays.stream(clients).map(String::trim).anyMatch(String::isEmpty)) {\n\t\t\tthrow new IllegalArgumentException(\"clients must not be empty\");\n\t\t}\n\t\tObjects.requireNonNull(samplingHandler, \"samplingHandler must not be null\");\n\t}\n\n}\n","sourceCodeStart":14,"sourceCodeEnd":38,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/sampling/SyncSamplingSpecification.java#L14-L38","documentation":"The SyncSamplingSpecification compact constructor requires a non-null clients array containing at least one non-blank entry; empty arrays or arrays of blank strings throw IllegalArgumentException with 'clients must not be empty'. The clients array names the MCP clients this sync sampling handler serves.","triggerScenarios":"new SyncSamplingSpecification(new String[0], handler) or with entries like new String[]{\"\"} or new String[]{\" \"} — empty or whitespace-only client names.","commonSituations":"Client lists sourced from empty properties/env config; string split producing an empty array; copy-pasted specification code where the client list was never filled in.","solutions":["Provide at least one concrete client name in the array","Validate the originating config/property list for emptiness before constructing the specification","Use the framework's mechanism for 'apply to all clients' rather than passing an empty array"],"exampleFix":"// before\nvar spec = new SyncSamplingSpecification(split(cfg), handler); // split -> []\n// after\nString[] clients = split(cfg);\nif (clients.length == 0) { clients = new String[]{\"default-client\"}; }\nvar spec = new SyncSamplingSpecification(clients, handler);","handlingStrategy":"validation","validationCode":"if (clients == null || clients.length == 0 || Arrays.stream(clients).map(String::trim).anyMatch(String::isEmpty)) {\n    throw new IllegalArgumentException(\"clients must contain at least one non-blank name\");\n}\nvar spec = new SyncSamplingSpecification(clients, handler);","typeGuard":null,"tryCatchPattern":"try { new SyncSamplingSpecification(clients, handler); } catch (IllegalArgumentException e) { applyDefaultClientList(); }","preventionTips":["Never build client arrays from unvalidated empty config","Filter blank strings before constructing the record","Test specification creation with boundary config values"],"tags":["validation","clients","sampling"],"backgroundTag":"empty-required-field","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}