fidl/
error.rs

1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Error (common to all fidl operations)
6
7use crate::handle::{ObjectType, Rights};
8use std::sync::Arc;
9use zx_status::Status;
10
11/// A specialized `Result` type for FIDL operations.
12pub type Result<T, E = Error> = std::result::Result<T, E>;
13
14#[derive(Debug, Clone, thiserror::Error)]
15#[allow(missing_docs)]
16pub enum TransportError {
17    #[error(transparent)]
18    Status(#[from] Status),
19    #[error(transparent)]
20    Other(Arc<dyn std::error::Error + Send + Sync>),
21}
22
23// This prevents some binary size bloat.
24impl Drop for TransportError {
25    #[inline(never)]
26    fn drop(&mut self) {}
27}
28
29/// The error type used by FIDL operations.
30#[derive(Debug, Clone, thiserror::Error)]
31#[non_exhaustive]
32#[allow(missing_docs)]
33pub enum Error {
34    #[error("Unexpected response to synchronous FIDL query.")]
35    UnexpectedSyncResponse,
36
37    #[error("Invalid FIDL boolean.")]
38    InvalidBoolean,
39
40    #[error("Invalid header for a FIDL buffer.")]
41    InvalidHeader,
42
43    #[error("Incompatible wire format magic number: {0}.")]
44    IncompatibleMagicNumber(u8),
45
46    #[error("Unsupported wire format version")]
47    UnsupportedWireFormatVersion,
48
49    #[error("Invalid FIDL buffer.")]
50    Invalid,
51
52    #[error(
53        "The FIDL object of size {expected} could not fit within the provided \
54        buffer range of size {actual}."
55    )]
56    OutOfRange { expected: usize, actual: usize },
57
58    #[error(
59        "The FIDL object requested more handles during decoding than were \
60        provided with the message."
61    )]
62    OutOfHandles,
63
64    #[error("Decoding the FIDL object did not use all of the bytes provided.")]
65    ExtraBytes,
66
67    #[error("Decoding the FIDL object did not use all of the handles provided.")]
68    ExtraHandles,
69
70    #[error(
71        "Decoding the FIDL object observed non-zero value in the padding region \
72        starting at byte {padding_start}."
73    )]
74    NonZeroPadding {
75        /// Index of the first byte of the padding, relative to the beginning of the message.
76        padding_start: usize,
77    },
78
79    #[error("The FIDL object had too many layers of out-of-line recursion.")]
80    MaxRecursionDepth,
81
82    #[error(
83        "There was an attempt to read or write a null-valued object as a non-nullable FIDL type."
84    )]
85    NotNullable,
86
87    #[error("A FIDL object reference with nonzero byte length had a null data pointer.")]
88    UnexpectedNullRef,
89
90    #[error("A FIDL message contained incorrectly encoded UTF8.")]
91    Utf8Error,
92
93    #[error("Vector was too long. Expected at most {max_length} elements, got {actual_length}.")]
94    VectorTooLong {
95        /// Maximum length, i.e. the `N` in `vector<T>:N`.
96        max_length: usize,
97        /// Actual length of the vector (number of elements).
98        actual_length: usize,
99    },
100
101    #[error("String was too long. Expected at most {max_bytes} bytes, got {actual_bytes}.")]
102    StringTooLong {
103        /// Maximum length in bytes, i.e. the `N` in `string:N`.
104        max_bytes: usize,
105        /// Actual length of the string in bytes.
106        actual_bytes: usize,
107    },
108
109    #[error(
110        "A message was received for ordinal value {ordinal} that the FIDL \
111        protocol {protocol_name} does not understand."
112    )]
113    UnknownOrdinal { ordinal: u64, protocol_name: &'static str },
114
115    #[error("Server for the FIDL protocol {protocol_name} did not recognize method {method_name}.")]
116    UnsupportedMethod { method_name: &'static str, protocol_name: &'static str },
117
118    #[error("Invalid bits value for a strict bits type.")]
119    InvalidBitsValue,
120
121    #[error("Invalid enum value for a strict enum type.")]
122    InvalidEnumValue,
123
124    #[error("Unrecognized descriminant for a FIDL union type.")]
125    UnknownUnionTag,
126
127    #[error("A FIDL future was polled after it had already completed.")]
128    PollAfterCompletion,
129
130    #[error(
131        "Received request with zero txid for two-way method ordinal, \
132        or nonzero txid for one-way method ordinal."
133    )]
134    InvalidRequestTxid,
135
136    #[error("Received response with unknown txid.")]
137    InvalidResponseTxid,
138
139    #[error("Received response with unexpected ordinal.")]
140    InvalidResponseOrdinal,
141
142    #[error("Invalid presence indicator.")]
143    InvalidPresenceIndicator,
144
145    #[error("Invalid inline bit in envelope.")]
146    InvalidInlineBitInEnvelope,
147
148    #[error("Invalid inline marker in envelope.")]
149    InvalidInlineMarkerInEnvelope,
150
151    #[error("Invalid number of bytes in FIDL envelope.")]
152    InvalidNumBytesInEnvelope,
153
154    #[error("Invalid number of handles in FIDL envelope.")]
155    InvalidNumHandlesInEnvelope,
156
157    #[error("Invalid FIDL handle used on the host.")]
158    InvalidHostHandle,
159
160    #[error("Incorrect handle subtype. Expected {}, but received {}", .expected.into_raw(), .received.into_raw())]
161    IncorrectHandleSubtype { expected: ObjectType, received: ObjectType },
162
163    #[error("Some expected handle rights are missing: {}", .missing_rights.bits())]
164    MissingExpectedHandleRights { missing_rights: Rights },
165
166    #[error("An error was encountered during handle replace()")]
167    HandleReplace(#[source] Status),
168
169    #[error("A server encountered an IO error writing a FIDL response to a channel: {0}")]
170    ServerResponseWrite(#[source] TransportError),
171
172    #[error(
173        "A FIDL server encountered an IO error reading incoming FIDL requests from a channel: {0}"
174    )]
175    ServerRequestRead(#[source] TransportError),
176
177    #[error("A FIDL server encountered an IO error writing an epitaph into a channel: {0}")]
178    ServerEpitaphWrite(#[source] TransportError),
179
180    #[error("A FIDL client encountered an IO error reading a response from a channel: {0}")]
181    ClientRead(#[source] TransportError),
182
183    #[error("A FIDL client encountered an IO error writing a request into a channel: {0}")]
184    ClientWrite(#[source] TransportError),
185
186    #[error("A FIDL client encountered an IO error issuing a channel call: {0}")]
187    ClientCall(#[source] Status),
188
189    #[error("A FIDL client encountered an IO error issuing a channel call: {0}")]
190    ClientEvent(#[source] Status),
191
192    #[cfg(not(target_os = "fuchsia"))]
193    #[error("A FIDL client's channel to the protocol {protocol_name} was closed: {status}, reason: {}",
194        .reason.as_ref().map(String::as_str).unwrap_or("not given")
195    )]
196    ClientChannelClosed {
197        /// The epitaph or `Status::PEER_CLOSED`.
198        #[source]
199        status: Status,
200        /// The name of the protocol at the other end of the channel.
201        protocol_name: &'static str,
202        /// The epitaph, if any. This can be used to discriminate channel closure with a
203        /// `Status::PEER_CLOSED` epitaph from a channel closure with no epitaph. Note that here,
204        /// the epitaph is treated as an opaque 32-bit integer.
205        epitaph: Option<u32>,
206        /// Further details on why exactly the channel closed.
207        reason: Option<String>,
208    },
209
210    #[cfg(target_os = "fuchsia")]
211    #[error("A FIDL client's channel to the protocol {protocol_name} was closed: {status}")]
212    ClientChannelClosed {
213        /// The epitaph or `Status::PEER_CLOSED`.
214        #[source]
215        status: Status,
216        /// The name of the protocol at the other end of the channel.
217        protocol_name: &'static str,
218        /// The epitaph, if any. This can be used to discriminate channel closure with a
219        /// `Status::PEER_CLOSED` epitaph from a channel closure with no epitaph. Note that here,
220        /// the epitaph is treated as an opaque 32-bit integer.
221        epitaph: Option<u32>,
222    },
223
224    #[error("There was an error attaching a FIDL channel to the async executor: {0}")]
225    AsyncChannel(#[source] Status),
226
227    #[cfg(target_os = "fuchsia")]
228    #[cfg(test)]
229    #[error("Test Status: {0}")]
230    TestIo(#[source] Status),
231}
232
233impl Error {
234    /// Returns `true` if the error was sourced by a closed channel.
235    pub fn is_closed(&self) -> bool {
236        matches!(self, Error::ClientChannelClosed { .. })
237    }
238}