@@ -177,15 +177,21 @@ fn parse_jsonrpc_message(
177177 return Err ( format ! ( "unsupported JSON-RPC version '{version}'" ) ) ;
178178 }
179179
180- if value. get ( "method" ) . is_some ( ) {
181- return parse_jsonrpc_call ( value) . map ( JsonRpcMessageInfo :: Call ) ;
180+ let has_method = value. get ( "method" ) . is_some ( ) ;
181+ let has_response_payload = jsonrpc_response_payload_present ( value) ;
182+ if has_method && has_response_payload {
183+ return Err ( "JSON-RPC message includes both method and result/error" . to_string ( ) ) ;
182184 }
183185
184- if jsonrpc_response_payload_present ( value ) {
186+ if has_response_payload {
185187 parse_jsonrpc_response ( value) ?;
186188 return Ok ( JsonRpcMessageInfo :: Response ) ;
187189 }
188190
191+ if has_method {
192+ return parse_jsonrpc_call ( value) . map ( JsonRpcMessageInfo :: Call ) ;
193+ }
194+
189195 Err ( "missing or non-string 'method' field" . to_string ( ) )
190196}
191197
@@ -484,6 +490,41 @@ mod tests {
484490 ) ;
485491 }
486492
493+ #[ test]
494+ fn rejects_message_with_method_and_result_or_error ( ) {
495+ let result_body = br#"{"jsonrpc":"2.0","id":1,"method":"initialize","result":{}}"# ;
496+ let result_info = parse_jsonrpc_body ( result_body) ;
497+ assert ! ( result_info. calls. is_empty( ) ) ;
498+ assert_eq ! (
499+ result_info. error. as_deref( ) ,
500+ Some ( "JSON-RPC message includes both method and result/error" )
501+ ) ;
502+
503+ let error_body = br#"{"jsonrpc":"2.0","id":1,"method":"initialize","error":{"code":-32603,"message":"failed"}}"# ;
504+ let error_info = parse_jsonrpc_body ( error_body) ;
505+ assert ! ( error_info. calls. is_empty( ) ) ;
506+ assert_eq ! (
507+ error_info. error. as_deref( ) ,
508+ Some ( "JSON-RPC message includes both method and result/error" )
509+ ) ;
510+ }
511+
512+ #[ test]
513+ fn rejects_batch_item_with_method_and_result ( ) {
514+ let body = br#"[
515+ {"jsonrpc":"2.0","id":1,"method":"tools/list"},
516+ {"jsonrpc":"2.0","id":2,"method":"initialize","result":{}}
517+ ]"# ;
518+ let info = parse_jsonrpc_body ( body) ;
519+
520+ assert ! ( info. calls. is_empty( ) ) ;
521+ assert ! ( info. is_batch) ;
522+ assert_eq ! (
523+ info. error. as_deref( ) ,
524+ Some ( "batch item invalid: JSON-RPC message includes both method and result/error" )
525+ ) ;
526+ }
527+
487528 #[ test]
488529 fn params_digest_is_canonical_and_redacted ( ) {
489530 let first = parse_jsonrpc_body (
0 commit comments