diff --git a/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java
index cbcb05752..816151f1b 100644
--- a/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java
+++ b/client/transport/grpc/src/main/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapper.java
@@ -74,7 +74,8 @@ public static A2AClientException mapGrpcError(Throwable e, String errorPrefix) {
String desc = message != null ? message : e.getMessage() == null ? "" : e.getMessage();
return switch (code) {
case NOT_FOUND -> new A2AClientException(errorPrefix + desc, new TaskNotFoundError());
- case UNIMPLEMENTED -> new A2AClientException(errorPrefix + desc, new UnsupportedOperationError());
+ case UNIMPLEMENTED, FAILED_PRECONDITION ->
+ new A2AClientException(errorPrefix + desc, new UnsupportedOperationError());
case INVALID_ARGUMENT -> new A2AClientException(errorPrefix + desc, new InvalidParamsError());
case INTERNAL -> new A2AClientException(errorPrefix + desc, new org.a2aproject.sdk.spec.InternalError(null, desc, null));
case UNAUTHENTICATED -> new A2AClientException(errorPrefix + A2AErrorMessages.AUTHENTICATION_FAILED);
diff --git a/client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java b/client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java
index 421d92cbb..1f5d0da75 100644
--- a/client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java
+++ b/client/transport/grpc/src/test/java/org/a2aproject/sdk/client/transport/grpc/GrpcErrorMapperTest.java
@@ -109,7 +109,21 @@ public void testTaskNotFoundErrorUnmarshalling() {
public void testUnsupportedOperationErrorUnmarshalling() {
String errorMessage = "Operation not supported";
StatusRuntimeException grpcException = createA2AStatusException(
- Status.Code.UNIMPLEMENTED.value(), errorMessage, "UNSUPPORTED_OPERATION");
+ Status.Code.FAILED_PRECONDITION.value(), errorMessage, "UNSUPPORTED_OPERATION");
+
+ A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException);
+
+ assertNotNull(result);
+ assertNotNull(result.getCause());
+ assertInstanceOf(UnsupportedOperationError.class, result.getCause());
+ }
+
+ @Test
+ public void testUnsupportedOperationErrorFallbackUsesFailedPrecondition() {
+ String errorMessage = "Operation not supported";
+ StatusRuntimeException grpcException = Status.FAILED_PRECONDITION
+ .withDescription(errorMessage)
+ .asRuntimeException();
A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException);
diff --git a/spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java b/spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java
index 79129944c..bbd84ccc2 100644
--- a/spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java
+++ b/spec/src/main/java/org/a2aproject/sdk/spec/A2AErrorCodes.java
@@ -26,7 +26,7 @@ public enum A2AErrorCodes {
PUSH_NOTIFICATION_NOT_SUPPORTED(-32003, "UNIMPLEMENTED", 400),
/** Error code indicating the requested operation is not supported (-32004). */
- UNSUPPORTED_OPERATION(-32004, "UNIMPLEMENTED", 400),
+ UNSUPPORTED_OPERATION(-32004, "FAILED_PRECONDITION", 400),
/** Error code indicating the content type is not supported (-32005). */
CONTENT_TYPE_NOT_SUPPORTED(-32005, "INVALID_ARGUMENT", 415),
diff --git a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java
index 3f739f182..ae222b5d4 100644
--- a/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java
+++ b/transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java
@@ -119,7 +119,7 @@
*
{@link org.a2aproject.sdk.spec.MethodNotFoundError} → {@link Status#NOT_FOUND}
* {@link org.a2aproject.sdk.spec.TaskNotFoundError} → {@link Status#NOT_FOUND}
* {@link org.a2aproject.sdk.spec.InternalError} → {@link Status#INTERNAL}
- * {@link org.a2aproject.sdk.spec.UnsupportedOperationError} → {@link Status#UNIMPLEMENTED}
+ * {@link org.a2aproject.sdk.spec.UnsupportedOperationError} → {@link Status#FAILED_PRECONDITION}
* {@link SecurityException} → {@link Status#UNAUTHENTICATED} or {@link Status#PERMISSION_DENIED}
*
*
@@ -746,7 +746,7 @@ private void installForkedContextWrapper(ServerCallContext context) {
* {@link TaskNotFoundError} → {@code NOT_FOUND}
* {@link TaskNotCancelableError} → {@code FAILED_PRECONDITION}
* {@link PushNotificationNotSupportedError} → {@code UNIMPLEMENTED}
- * {@link UnsupportedOperationError} → {@code UNIMPLEMENTED}
+ * {@link UnsupportedOperationError} → {@code FAILED_PRECONDITION}
* {@link JSONParseError} → {@code INTERNAL}
* {@link ContentTypeNotSupportedError} → {@code INVALID_ARGUMENT}
* {@link InvalidAgentResponseError} → {@code INTERNAL}
diff --git a/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java
index 974d99e00..f88186fc5 100644
--- a/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java
+++ b/transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java
@@ -161,7 +161,7 @@ public void testOnCancelTaskNotSupported() throws Exception {
handler.cancelTask(request, streamRecorder);
streamRecorder.awaitCompletion(5, TimeUnit.SECONDS);
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -218,7 +218,7 @@ public void testOnMessageError() throws Exception {
agentEmitter.fail(new UnsupportedOperationError());
};
StreamRecorder streamRecorder = sendMessageRequest(handler);
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -286,7 +286,7 @@ public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception {
GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor);
StreamRecorder streamRecorder = getTaskPushNotificationConfigRequest(handler,
AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id());
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -301,7 +301,7 @@ public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception {
GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor);
StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler,
AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id());
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -625,7 +625,7 @@ public void testStreamingNotSupportedError() throws Exception {
AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true);
GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor);
StreamRecorder streamRecorder = sendStreamingMessageRequest(handler);
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -639,7 +639,7 @@ public void testStreamingNotSupportedErrorOnSubscribeToTask() throws Exception {
StreamRecorder streamRecorder = StreamRecorder.create();
handler.subscribeToTask(request, streamRecorder);
streamRecorder.awaitCompletion(5, TimeUnit.SECONDS);
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -735,7 +735,7 @@ public void testListPushNotificationConfigNoPushConfigStore() {
.build();
StreamRecorder streamRecorder = StreamRecorder.create();
handler.listTaskPushNotificationConfigs(request, streamRecorder);
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Test
@@ -806,7 +806,7 @@ public void testDeletePushNotificationConfigNoPushConfigStore() {
.build();
StreamRecorder streamRecorder = StreamRecorder.create();
handler.deleteTaskPushNotificationConfig(request, streamRecorder);
- assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
+ assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION);
}
@Disabled