google_cloud_pubsub/error.rs
1// Copyright 2026 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Custom errors for the Cloud Pub/Sub clients.
16
17use crate::Error;
18use std::sync::Arc;
19
20/// Represents an error that can occur when publishing a message.
21#[derive(thiserror::Error, Debug)]
22#[non_exhaustive]
23pub enum PublishError {
24 /// The underlying RPC failed.
25 ///
26 /// The inner error is wrapped in an [`Arc`] because the same error may
27 /// affect multiple [`publish()`](crate::client::Publisher::publish) calls.
28 #[error("the publish operation was interrupted by an error: {0}")]
29 Rpc(#[source] Arc<Error>),
30
31 /// Publishing is paused because a previous message with the same ordering key failed.
32 ///
33 /// To prevent messages from being sent out of order, the [`Publisher`](crate::client::Publisher)
34 /// paused messages for the ordering key.
35 ///
36 /// To resume publishing, call [`Publisher::resume_publish`](crate::client::Publisher::resume_publish).
37 #[error("publishing is paused for the ordering key")]
38 OrderingKeyPaused,
39
40 /// The operation failed because the [`Publisher`](crate::client::Publisher) has
41 /// been shut down.
42 ///
43 /// Typically this can happen when the application is shutting down. Some background
44 /// tasks in the client library may be terminated before they can send all the
45 /// pending messages.
46 #[error("the publisher has shut down")]
47 Shutdown,
48}
49
50/// Represents an error that can occur when acking or nacking a message.
51#[derive(thiserror::Error, Debug)]
52#[non_exhaustive]
53pub enum AckError {
54 /// The message's lease expired before the client could ack or nack it.
55 ///
56 /// The message has not been acked, and will be redelivered, maybe to
57 /// another client.
58 #[error("the message's lease has already expired. It was not acked, and will be redelivered.")]
59 LeaseExpired,
60
61 /// The underlying RPC failed.
62 #[non_exhaustive]
63 #[error("the operation failed. RPC error: {source}")]
64 Rpc {
65 /// The error returned by the service for the request.
66 #[source]
67 source: Arc<Error>,
68 },
69
70 /// Lease management shutdown before the client could acknowledge the
71 /// message.
72 ///
73 /// The client did not acknowledge the message. The service will redeliver
74 /// message.
75 #[error(
76 "shutdown before attempting the operation. \
77 The message was not acknowledged, and will be redelivered."
78 )]
79 ShutdownBeforeAck,
80
81 /// Error during shutdown.
82 ///
83 /// The result of the operation is unknown. If you attempted to ack
84 /// the message, the service may or may not redeliver it.
85 #[error("error during shutdown. The result of the operation is unknown. {0}")]
86 Shutdown(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use google_cloud_gax::error::rpc::{Code, Status};
93
94 #[test]
95 fn ack_error_rpc_debug() {
96 let e = AckError::Rpc {
97 source: Arc::new(Error::service(
98 Status::default()
99 .set_code(Code::FailedPrecondition)
100 .set_message("inner fail"),
101 )),
102 };
103 let fmt = format!("{e}");
104 assert!(fmt.contains("operation failed."), "{fmt}");
105 assert!(fmt.contains("inner fail"), "{fmt}");
106 }
107}