#[non_exhaustive]pub struct A2aError {
pub code: ErrorCode,
pub message: String,
pub data: Option<Value>,
/* private fields */
}Expand description
The canonical error type for A2A protocol operations.
Carries an ErrorCode, a human-readable message, and an optional
data payload (arbitrary JSON) for additional diagnostics.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.code: ErrorCodeMachine-readable error code.
message: StringHuman-readable error message.
data: Option<Value>Optional structured error details.
Implementations§
Source§impl A2aError
impl A2aError
Sourcepub const fn metric_label(&self) -> &'static str
pub const fn metric_label(&self) -> &'static str
A bounded, low-cardinality label for this error, for metric attributes.
Delegates to ErrorCode::metric_label. Never the free-form message,
which can carry request-derived text — using that as a metric dimension
is how a client turns an error into unbounded cardinality.
Sourcepub fn new(code: ErrorCode, message: impl Into<String>) -> A2aError
pub fn new(code: ErrorCode, message: impl Into<String>) -> A2aError
Creates a new A2aError with the given code and message.
Sourcepub fn with_data(
code: ErrorCode,
message: impl Into<String>,
data: Value,
) -> A2aError
pub fn with_data( code: ErrorCode, message: impl Into<String>, data: Value, ) -> A2aError
Creates a new A2aError with the given code, message, and data.
Sourcepub fn unauthenticated(
message: impl Into<String>,
challenge: impl Into<String>,
) -> A2aError
pub fn unauthenticated( message: impl Into<String>, challenge: impl Into<String>, ) -> A2aError
Refuses a request that carries no usable credential: HTTP 401 with
challenge as its WWW-Authenticate header (e.g.
Bearer realm="a2a"), gRPC UNAUTHENTICATED. Over JSON-RPC the body
is an Invalid Request (-32600), as it was before the refusal had a
status of its own.
Return it from an a2a-protocol-server ServerInterceptor that
authenticates. message reaches the caller, so it should not say
why the credential failed.
Sourcepub fn permission_denied(message: impl Into<String>) -> A2aError
pub fn permission_denied(message: impl Into<String>) -> A2aError
Refuses an authenticated caller the operation: HTTP 403, gRPC
PERMISSION_DENIED, JSON-RPC Invalid Request (-32600). Spec §3.3.2:
it must not reveal whether a resource the caller cannot see exists.
Sourcepub const fn auth_rejection(&self) -> Option<&AuthRejection>
pub const fn auth_rejection(&self) -> Option<&AuthRejection>
The credential refusal this error carries, if it is one. Set only by
unauthenticated and
permission_denied, and never read from
the wire.
Sourcepub fn task_not_found(task_id: impl Display) -> A2aError
pub fn task_not_found(task_id: impl Display) -> A2aError
Creates a “Task not found” error for the given task ID string.
Sourcepub fn task_not_cancelable(task_id: impl Display) -> A2aError
pub fn task_not_cancelable(task_id: impl Display) -> A2aError
Creates a “Task not cancelable” error.
Sourcepub fn internal(msg: impl Into<String>) -> A2aError
pub fn internal(msg: impl Into<String>) -> A2aError
Creates an internal error with the provided message.
Sourcepub fn invalid_params(msg: impl Into<String>) -> A2aError
pub fn invalid_params(msg: impl Into<String>) -> A2aError
Creates an “Invalid params” error.
Sourcepub fn is_stream_lagged(&self) -> bool
pub fn is_stream_lagged(&self) -> bool
Returns true when this error is the recoverable consumer-lag signal
a server emits on a streaming subscription.
This is not a terminal error. The server surfaces it to say “you
read too slowly and n events were dropped”; the stream continues, and
a consumer that keeps polling still receives every later event,
including the terminal status. A consumer that treats it like any other
error and stops reading will silently miss the end of the task.
It is detected by the STREAM_LAGGED_MARKER key in A2aError::data
rather than by code or message, because the code is a generic
InternalError and the message is human-facing prose.
use a2a_protocol_types::error::{A2aError, ErrorCode};
let lag = A2aError::stream_lagged(7);
assert!(lag.is_stream_lagged());
assert_eq!(lag.dropped_event_count(), Some(7));
// An ordinary internal error is not a lag signal.
assert!(!A2aError::internal("boom").is_stream_lagged());
assert!(!A2aError::new(ErrorCode::TaskNotFound, "gone").is_stream_lagged());Sourcepub fn dropped_event_count(&self) -> Option<u64>
pub fn dropped_event_count(&self) -> Option<u64>
Returns how many events were dropped, when this is a consumer-lag
signal (see A2aError::is_stream_lagged); None otherwise.
Sourcepub fn stream_lagged(dropped: u64) -> A2aError
pub fn stream_lagged(dropped: u64) -> A2aError
Builds the consumer-lag signal carrying dropped.
Servers emit this; consumers identify it with
A2aError::is_stream_lagged. It lives here rather than in the server
crate so that both sides — and any third-party client — agree on one
definition of the marker.
Sourcepub fn unsupported_operation(msg: impl Into<String>) -> A2aError
pub fn unsupported_operation(msg: impl Into<String>) -> A2aError
Creates an “Unsupported operation” error.
Sourcepub fn parse_error(msg: impl Into<String>) -> A2aError
pub fn parse_error(msg: impl Into<String>) -> A2aError
Creates a “Parse error” error.
Sourcepub fn invalid_agent_response(msg: impl Into<String>) -> A2aError
pub fn invalid_agent_response(msg: impl Into<String>) -> A2aError
Creates an “Invalid agent response” error.
Sourcepub fn extended_card_not_configured(msg: impl Into<String>) -> A2aError
pub fn extended_card_not_configured(msg: impl Into<String>) -> A2aError
Creates an “Extended agent card not configured” error.
Sourcepub fn push_not_supported(msg: impl Into<String>) -> A2aError
pub fn push_not_supported(msg: impl Into<String>) -> A2aError
Creates a “Push notification not supported” error.
Sourcepub fn content_type_not_supported(msg: impl Into<String>) -> A2aError
pub fn content_type_not_supported(msg: impl Into<String>) -> A2aError
Creates a “Content type not supported” error.
Sourcepub fn extension_support_required(msg: impl Into<String>) -> A2aError
pub fn extension_support_required(msg: impl Into<String>) -> A2aError
Creates an “Extension support required” error.
Sourcepub fn version_not_supported(msg: impl Into<String>) -> A2aError
pub fn version_not_supported(msg: impl Into<String>) -> A2aError
Creates a “Version not supported” error.
Sourcepub fn error_info_data(&self, metadata: Option<Value>) -> Value
pub fn error_info_data(&self, metadata: Option<Value>) -> Value
Builds the google.rpc.ErrorInfo data array as required by the spec.
Per Section 9.5, 10.6, and 11.6, A2A-specific errors MUST include
an ErrorInfo entry with @type, reason, domain, and optional metadata.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for A2aError
impl<'de> Deserialize<'de> for A2aError
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<A2aError, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<A2aError, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Error for A2aError
impl Error for A2aError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<A2aError> for ClientError
impl From<A2aError> for ClientError
Source§fn from(e: A2aError) -> ClientError
fn from(e: A2aError) -> ClientError
Source§impl From<A2aError> for ServerError
impl From<A2aError> for ServerError
Source§fn from(e: A2aError) -> ServerError
fn from(e: A2aError) -> ServerError
Source§impl From<ClientError> for A2aError
Lets an executor that delegates to another agent use ? on client calls.
impl From<ClientError> for A2aError
Lets an executor that delegates to another agent use ? on client calls.
An AgentExecutor returns A2aResult, so without this every delegated
call had to be flattened to a string, losing whether it was worth
retrying. The conversion keeps what the server needs to classify the
failed task (see a2a_protocol_types::failure::error_class):
ClientError | A2aError code | Failure class |
|---|---|---|
Protocol(e) | e.code, with e.message and e.data unchanged | from the code |
anything is_retryable — timeouts, connection failures, 429/502/503/504, TooManyPendingRequests | InternalError | Transient |
Serialization (the peer sent something unreadable) | InvalidAgentResponse | Internal |
| everything else (bad endpoint, binding mismatch, other statuses, auth required) | InternalError | Internal |
“Transient exactly when the client would retry” is deliberate: the
client’s retry policy and the caller’s are then the same judgement.
The class rides in data under the failure key; the server never sends
data to its caller as-is, so it does not leak. The message is
downstream A2A call failed: followed by this error’s text and its
source chain, so nothing the client knew is lost.
use a2a_protocol_client::ClientBuilder;
use a2a_protocol_types::error::A2aResult;
use a2a_protocol_types::params::TaskQueryParams;
// The shape of an `AgentExecutor::execute` body that delegates.
async fn delegate(downstream: &str, task_id: &str) -> A2aResult<String> {
let client = ClientBuilder::new(downstream).build()?;
let task = client
.get_task(TaskQueryParams {
tenant: None,
id: task_id.to_owned(),
history_length: None,
})
.await?; // a timeout here fails the task as `Transient`
Ok(task.text().unwrap_or_default().to_owned())
}Source§fn from(e: ClientError) -> A2aError
fn from(e: ClientError) -> A2aError
Source§impl From<TerminalStateConflict> for A2aError
impl From<TerminalStateConflict> for A2aError
Source§fn from(conflict: TerminalStateConflict) -> A2aError
fn from(conflict: TerminalStateConflict) -> A2aError
Source§impl Serialize for A2aError
impl Serialize for A2aError
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for A2aError
impl RefUnwindSafe for A2aError
impl Send for A2aError
impl Sync for A2aError
impl Unpin for A2aError
impl UnsafeUnpin for A2aError
impl UnwindSafe for A2aError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request