{"record":{"id":"bfef19ad6d9ad37b","repo":"spring-projects/spring-ai","slug":"either-prompt-or-uri-must-be-provided","errorCode":null,"errorMessage":"Either prompt or uri must be provided!","messagePattern":"Either prompt or uri must be provided!","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java","lineNumber":87,"sourceCode":"\n\t/**\n\t * Constructor for AbstractMcpCompleteMethodCallback.\n\t * @param method The method to create a callback for\n\t * @param bean The bean instance that contains the method\n\t * @param prompt The prompt reference\n\t * @param uri The URI reference\n\t * @param uriTemplateManagerFactory The URI template manager factory\n\t */\n\tprotected AbstractMcpCompleteMethodCallback(Method method, Object bean, String prompt, String uri,\n\t\t\tMcpUriTemplateManagerFactory uriTemplateManagerFactory) {\n\n\t\tAssert.notNull(method, \"Method can't be null!\");\n\t\tAssert.notNull(bean, \"Bean can't be null!\");\n\t\tAssert.notNull(uriTemplateManagerFactory, \"URI template manager factory can't be null!\");\n\n\t\t// Either prompt or uri must be provided, but not both\n\t\tif ((prompt == null || prompt.isEmpty()) && (uri == null || uri.isEmpty())) {\n\t\t\tthrow new IllegalArgumentException(\"Either prompt or uri must be provided!\");\n\t\t}\n\t\tif ((prompt != null && !prompt.isEmpty()) && (uri != null && !uri.isEmpty())) {\n\t\t\tthrow new IllegalArgumentException(\"Only one of prompt or uri can be provided!\");\n\t\t}\n\n\t\tthis.method = method;\n\t\tthis.bean = bean;\n\t\tthis.prompt = prompt;\n\t\tthis.uri = uri;\n\n\t\t// Create the CompleteReference based on prompt or uri\n\t\tif (prompt != null && !prompt.isEmpty()) {\n\t\t\tthis.completeReference = McpSchema.PromptReference.builder(prompt).build();\n\t\t}\n\t\telse {\n\t\t\tthis.completeReference = new McpSchema.ResourceReference(uri);\n\t\t}\n","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java#L69-L105","documentation":"AbstractMcpCompleteMethodCallback's constructor requires that a completion callback provide exactly one completion target: either a prompt name or a resource URI. When both are absent (null or empty), it throws this IllegalArgumentException at registration time because the callback would have nothing to complete against.","triggerScenarios":"Registering an @McpComplete-annotated completion method without setting either the prompt attribute or the uri attribute (both null/empty) in the specification or annotation.","commonSituations":"Forgetting the prompt attribute when moving from resource completion to prompt completion; copying a builder call and deleting both attributes; annotation processor not picking up default attribute values.","solutions":["Set the prompt attribute if the completion is for a prompt: e.g. prompt = \"myPrompt\".","Set the uri attribute instead if the completion is for a resource template: e.g. uri = \"file:///documents/{path}\".","Ensure exactly one of the two is populated (see error 84 for the both-set case)."],"exampleFix":"// before\nnew AbstractMcpCompleteMethodCallback(method, bean, null, null, factory); // throws\n// after\nnew AbstractMcpCompleteMethodCallback(method, bean, \"myPrompt\", null, factory);","handlingStrategy":"validation","validationCode":"boolean hasPrompt = prompt != null && !prompt.isEmpty();\nboolean hasUri = uri != null && !uri.isEmpty();\nif (!hasPrompt && !hasUri) throw new IllegalStateException(\"set either prompt or uri for @McpComplete\");","typeGuard":null,"tryCatchPattern":"try {\n    registry.registerCompleteCallback(method, bean, prompt, uri);\n} catch (IllegalArgumentException e) {\n    LOG.error(\"completion registration failed: {}\", e.getMessage());\n}","preventionTips":["Always specify exactly one completion target (prompt or uri) on @McpComplete.","Review annotation attributes after copy-pasting completion handlers.","Add a startup check that scans @McpComplete methods for a target attribute."],"tags":["mcp","validation","completion","java"],"backgroundTag":"missing-required-argument","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}