diff --git a/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift b/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift
index 6119a23779a6a8304faca9a3fc0e5ea6c7dab4d4..46cfdbfa7103029615bd525abd78d8f54dfa3a10 100644
--- a/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift
+++ b/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift
@@ -39,12 +39,14 @@ public struct ChatState: Equatable, Identifiable {
     myContactId: Data? = nil,
     messages: IdentifiedArrayOf<Message> = [],
     failure: String? = nil,
+    sendFailure: String? = nil,
     text: String = ""
   ) {
     self.id = id
     self.myContactId = myContactId
     self.messages = messages
     self.failure = failure
+    self.sendFailure = sendFailure
     self.text = text
   }
 
@@ -52,6 +54,7 @@ public struct ChatState: Equatable, Identifiable {
   public var myContactId: Data?
   public var messages: IdentifiedArrayOf<Message>
   public var failure: String?
+  public var sendFailure: String?
   @BindableState public var text: String
 }
 
@@ -59,6 +62,8 @@ public enum ChatAction: Equatable, BindableAction {
   case start
   case didFetchMessages(IdentifiedArrayOf<ChatState.Message>)
   case sendTapped
+  case sendFailed(String)
+  case dismissSendFailureTapped
   case binding(BindingAction<ChatState>)
 }
 
@@ -152,8 +157,7 @@ public let chatReducer = Reducer<ChatState, ChatAction, ChatEnvironment>
           text: text,
           to: recipientId,
           onError: { error in
-            // TODO: handle error
-            print("^^^ ERROR: \(error)")
+            subscriber.send(.sendFailed(error.localizedDescription))
           },
           completion: {
             subscriber.send(completion: .finished)
@@ -166,6 +170,14 @@ public let chatReducer = Reducer<ChatState, ChatAction, ChatEnvironment>
     .receive(on: env.mainQueue)
     .eraseToEffect()
 
+  case .sendFailed(let failure):
+    state.sendFailure = failure
+    return .none
+
+  case .dismissSendFailureTapped:
+    state.sendFailure = nil
+    return .none
+
   case .binding(_):
     return .none
   }
diff --git a/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift b/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift
index f80657422f63520954194f3350a14a0d79d62c75..1a513af07195076dabb987bee120111411a6c633 100644
--- a/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift
@@ -169,4 +169,42 @@ final class ChatFeatureTests: XCTestCase {
 
     sendMessageCompletion?()
   }
+
+  func testSendFailure() {
+    var sendMessageOnError: SendMessage.OnError?
+    var sendMessageCompletion: SendMessage.Completion?
+
+    let store = TestStore(
+      initialState: ChatState(
+        id: .contact("contact-id".data(using: .utf8)!),
+        text: "Hello"
+      ),
+      reducer: chatReducer,
+      environment: .unimplemented
+    )
+
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
+    store.environment.sendMessage.run = { _, _, onError, completion in
+      sendMessageOnError = onError
+      sendMessageCompletion = completion
+    }
+
+    store.send(.sendTapped) {
+      $0.text = ""
+    }
+
+    let error = NSError(domain: "test", code: 123)
+    sendMessageOnError?(error)
+
+    store.receive(.sendFailed(error.localizedDescription)) {
+      $0.sendFailure = error.localizedDescription
+    }
+
+    sendMessageCompletion?()
+
+    store.send(.dismissSendFailureTapped) {
+      $0.sendFailure = nil
+    }
+  }
 }