@@ -36,18 +36,63 @@ public static A2AClientException mapRestError(String body, int code) {
3636 try {
3737 if (body != null && !body .isBlank ()) {
3838 JsonObject node = JsonUtil .fromJson (body , JsonObject .class );
39+ // Support RFC 7807 Problem Details format (type, title, details, status)
40+ if (node .has ("type" )) {
41+ String type = node .get ("type" ).getAsString ();
42+ String errorMessage = node .has ("title" ) ? node .get ("title" ).getAsString () : "" ;
43+ return mapRestErrorByType (type , errorMessage , code );
44+ }
45+ // Legacy format (error, message)
3946 String className = node .has ("error" ) ? node .get ("error" ).getAsString () : "" ;
4047 String errorMessage = node .has ("message" ) ? node .get ("message" ).getAsString () : "" ;
41- return mapRestError (className , errorMessage , code );
48+ return mapRestErrorByClassName (className , errorMessage , code );
4249 }
43- return mapRestError ("" , "" , code );
50+ return mapRestErrorByClassName ("" , "" , code );
4451 } catch (JsonProcessingException ex ) {
4552 Logger .getLogger (RestErrorMapper .class .getName ()).log (Level .SEVERE , null , ex );
4653 return new A2AClientException ("Failed to parse error response: " + ex .getMessage ());
4754 }
4855 }
4956
5057 public static A2AClientException mapRestError (String className , String errorMessage , int code ) {
58+ return mapRestErrorByClassName (className , errorMessage , code );
59+ }
60+
61+ /**
62+ * Maps RFC 7807 Problem Details error type URIs to A2A exceptions.
63+ * <p>
64+ * Note: Error constructors receive null for code and data parameters because:
65+ * <ul>
66+ * <li>Error codes are defaulted by each error class (e.g., -32007 for ExtendedAgentCardNotConfiguredError)</li>
67+ * <li>The message comes from the RFC 7807 "title" field</li>
68+ * <li>The data field is optional and not included in basic RFC 7807 responses</li>
69+ * </ul>
70+ *
71+ * @param type the RFC 7807 error type URI (e.g., "https://a2a-protocol.org/errors/task-not-found")
72+ * @param errorMessage the error message from the "title" field
73+ * @param code the HTTP status code (currently unused, kept for consistency)
74+ * @return an A2AClientException wrapping the appropriate A2A error
75+ */
76+ private static A2AClientException mapRestErrorByType (String type , String errorMessage , int code ) {
77+ return switch (type ) {
78+ case "https://a2a-protocol.org/errors/task-not-found" -> new A2AClientException (errorMessage , new TaskNotFoundError ());
79+ case "https://a2a-protocol.org/errors/extended-agent-card-not-configured" -> new A2AClientException (errorMessage , new ExtendedAgentCardNotConfiguredError (null , errorMessage , null ));
80+ case "https://a2a-protocol.org/errors/content-type-not-supported" -> new A2AClientException (errorMessage , new ContentTypeNotSupportedError (null , errorMessage , null ));
81+ case "https://a2a-protocol.org/errors/internal-error" -> new A2AClientException (errorMessage , new InternalError (errorMessage ));
82+ case "https://a2a-protocol.org/errors/invalid-agent-response" -> new A2AClientException (errorMessage , new InvalidAgentResponseError (null , errorMessage , null ));
83+ case "https://a2a-protocol.org/errors/invalid-params" -> new A2AClientException (errorMessage , new InvalidParamsError ());
84+ case "https://a2a-protocol.org/errors/invalid-request" -> new A2AClientException (errorMessage , new InvalidRequestError ());
85+ case "https://a2a-protocol.org/errors/method-not-found" -> new A2AClientException (errorMessage , new MethodNotFoundError ());
86+ case "https://a2a-protocol.org/errors/push-notification-not-supported" -> new A2AClientException (errorMessage , new PushNotificationNotSupportedError ());
87+ case "https://a2a-protocol.org/errors/task-not-cancelable" -> new A2AClientException (errorMessage , new TaskNotCancelableError ());
88+ case "https://a2a-protocol.org/errors/unsupported-operation" -> new A2AClientException (errorMessage , new UnsupportedOperationError ());
89+ case "https://a2a-protocol.org/errors/extension-support-required" -> new A2AClientException (errorMessage , new ExtensionSupportRequiredError (null , errorMessage , null ));
90+ case "https://a2a-protocol.org/errors/version-not-supported" -> new A2AClientException (errorMessage , new VersionNotSupportedError (null , errorMessage , null ));
91+ default -> new A2AClientException (errorMessage );
92+ };
93+ }
94+
95+ private static A2AClientException mapRestErrorByClassName (String className , String errorMessage , int code ) {
5196 return switch (className ) {
5297 case "io.a2a.spec.TaskNotFoundError" -> new A2AClientException (errorMessage , new TaskNotFoundError ());
5398 case "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException (errorMessage , new ExtendedAgentCardNotConfiguredError (null , errorMessage , null ));
0 commit comments