diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift
index 4b41931743547862b2395e2a75201b85709c9464..2028fc2de02497b066e8181bdf6912109973a06f 100644
--- a/Sources/ChatFeature/Controllers/SingleChatController.swift
+++ b/Sources/ChatFeature/Controllers/SingleChatController.swift
@@ -530,12 +530,14 @@ extension SingleChatController: KeyboardListenerDelegate {
     }
 
     func keyboardWillChangeFrame(info: KeyboardInfo) {
-        let keyWindow: UIWindow? = UIApplication.shared.connectedScenes
-            .filter { $0.activationState == .foregroundActive }
-            .compactMap { $0 as? UIWindowScene }
-            .first?
-            .windows
-            .first(where: \.isKeyWindow)
+        let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
+
+//        let keyWindow: UIWindow? = UIApplication.shared.connectedScenes
+//            .filter { $0.activationState == .foregroundActive }
+//            .compactMap { $0 as? UIWindowScene }
+//            .first?
+//            .windows
+//            .first(where: \.isKeyWindow)
 
         guard let keyWindow = keyWindow else {
             fatalError("[keyboardWillChangeFrame]: Couldn't get key window")
diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift
index 43ae7a6f6e2af4021fc1070c704a2ea0d499f250..6c27c1de9b35b4b3f2fe55d8eca4948e984848c8 100644
--- a/Sources/LaunchFeature/LaunchViewModel.swift
+++ b/Sources/LaunchFeature/LaunchViewModel.swift
@@ -81,7 +81,11 @@ final class LaunchViewModel {
             self.versionChecker().sink { [unowned self] in
                 switch $0 {
                 case .upToDate:
-                    self.updateBannedList { self.continueWithInitialization() }
+                    self.updateBannedList {
+                        self.updateErrors {
+                            self.continueWithInitialization()
+                        }
+                    }
                 case .failure(let error):
                     self.versionFailed(error: error)
                 case .updateRequired(let info):
@@ -97,7 +101,7 @@ final class LaunchViewModel {
         do {
             try self.setupDatabase()
 
-            try SetLogLevel.live(.trace)
+            _ = try SetLogLevel.live(.trace)
 
             guard let certPath = Bundle.module.path(forResource: "cmix.rip", ofType: "crt"),
                   let contactFilePath = Bundle.module.path(forResource: "udContact", ofType: "bin") else {
@@ -326,6 +330,32 @@ final class LaunchViewModel {
         }
     }
 
+    private func updateErrors(completion: @escaping () -> Void) {
+        let errorsURLString = "https://git.xx.network/elixxir/client-error-database/-/raw/main/clientErrors.json"
+
+        URLSession.shared.dataTask(with: URL(string: errorsURLString)!) { [weak self] data, _, error in
+            guard let self = self else { return }
+
+            guard error == nil else {
+                print(">>> Issue when trying to download errors json: \(error!.localizedDescription)")
+                self.updateErrors(completion: completion)
+                return
+            }
+
+            guard let data = data, let json = String(data: data, encoding: .utf8) else {
+                print(">>> Issue when trying to unwrap errors json")
+                return
+            }
+
+            do {
+                try UpdateCommonErrors.live(jsonFile: json)
+                completion()
+            } catch {
+                print(">>> Issue when trying to update common errors: \(error.localizedDescription)")
+            }
+        }.resume()
+    }
+
     private func updateBannedList(completion: @escaping () -> Void) {
         fetchBannedList { result in
             switch result {
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift
index d379b9cc0326fde68d59cf7ba386a20a7007c2d8..756479e25a56b544766ab694596bccc688216828 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift
@@ -78,7 +78,8 @@ final class OnboardingEmailConfirmationViewModel {
                 self.hudRelay.send(.none)
                 self.completionRelay.send(self.confirmation)
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
index 982623286266f322bff1f264c7da42bc4e16f6e9..cf21d93b4fd005bb991595e991b066c703bf48fe 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
@@ -4,8 +4,8 @@ import Models
 import Shared
 import Combine
 import Defaults
-import InputField
 import XXClient
+import InputField
 import CombineSchedulers
 import DependencyInjection
 import XXMessengerClient
@@ -56,7 +56,8 @@ final class OnboardingEmailViewModel {
                     confirmationId: confirmationId
                 )
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift
index 49e1570802766348885c1e339eda39497aa14a15..ba335ba8092e751dae7e1092947bb48ce31b9348 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift
@@ -78,7 +78,8 @@ final class OnboardingPhoneConfirmationViewModel {
                 self.hudRelay.send(.none)
                 self.completionRelay.send(self.confirmation)
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
index a3141d2c25e8379bc190ddad86aae5a06ff8dab1..f226397f4faa6d8afc4c9de36c505ffa5b6762fe 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
@@ -67,7 +67,8 @@ final class OnboardingPhoneViewModel {
                     confirmationId: confirmationId
                 )
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
index 39d71f1a673292cf001f531df614f0a1112b8d85..b042341ce209a880374a9fcba1841f7e67e4cfe2 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
@@ -4,6 +4,7 @@ import Models
 import Combine
 import Defaults
 import XXModels
+import XXClient
 import InputField
 import Foundation
 import XXMessengerClient
@@ -75,7 +76,7 @@ final class OnboardingUsernameViewModel {
                 self.greenRelay.send()
             } catch {
                 self.hudRelay.send(.none)
-                self.stateRelay.value.status = .invalid(error.localizedDescription)
+                self.stateRelay.value.status = .invalid(CreateUserFriendlyErrorMessage.live(error.localizedDescription))
             }
         }
     }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
index 8edf40aacd81caceb86882ff1096cf20360cc164..4a192c306e329bfadb92142ee0d453fc19c8de6c 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
@@ -59,7 +59,8 @@ final class ProfileEmailViewModel {
                     confirmationId: confirmationId
                 )
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
index e5504140093d8157af0b6ef1b06c2ebaf7baeea5..bbf580a249e2da6e8041dce235e8a3769ea19952 100644
--- a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
@@ -68,7 +68,8 @@ final class ProfilePhoneViewModel {
                 )
 
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
index 57334dcf20f25d00d0e4b6acfdb9dde45f911218..36006fa591b7841c762bfb429f1f67a1a5c9e07b 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
@@ -109,7 +109,8 @@ final class ProfileViewModel {
                 self.hudRelay.send(.none)
                 self.refresh()
             } catch {
-                self.hudRelay.send(.error(.init(with: error)))
+                let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+                self.hudRelay.send(.error(.init(content: xxError)))
             }
         }
     }
diff --git a/Sources/ScanFeature/Controllers/ScanController.swift b/Sources/ScanFeature/Controllers/ScanController.swift
index 2a1b99aa6da269007f9692b5ebb0b3b81e6ca377..52055ac4eae74504e4f53edfb78617099079716e 100644
--- a/Sources/ScanFeature/Controllers/ScanController.swift
+++ b/Sources/ScanFeature/Controllers/ScanController.swift
@@ -83,8 +83,7 @@ final class ScanController: UIViewController {
             .sink { [unowned self] in coordinator.toContact($0, from: self) }
             .store(in: &cancellables)
 
-        viewModel.state
-            .map(\.status)
+        viewModel.statePublisher
             .removeDuplicates()
             .receive(on: DispatchQueue.main)
             .sink { [unowned self] in
diff --git a/Sources/ScanFeature/ViewModels/ScanViewModel.swift b/Sources/ScanFeature/ViewModels/ScanViewModel.swift
index 365533cdc2b20c4eb6b97d89c92feee72d8f2172..b58546fb542279cdef56390e1c0111c8c502ed5e 100644
--- a/Sources/ScanFeature/ViewModels/ScanViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanViewModel.swift
@@ -2,9 +2,9 @@ import Shared
 import Models
 import Combine
 import XXModels
-import Foundation
 import XXClient
-import CombineSchedulers
+import Foundation
+import ReportingFeature
 import DependencyInjection
 
 enum ScanStatus: Equatable {
@@ -21,93 +21,77 @@ enum ScanError: Equatable {
     case alreadyFriends(String)
 }
 
-struct ScanViewState: Equatable {
-    var status: ScanStatus = .reading
-}
-
 final class ScanViewModel {
     @Dependency var database: Database
-    @Dependency var getFactsFromContact: GetFactsFromContact
+    @Dependency var reportingStatus: ReportingStatus
 
-    var backgroundScheduler: AnySchedulerOf<DispatchQueue>
-        = DispatchQueue.global().eraseToAnyScheduler()
+    var contactPublisher: AnyPublisher<XXModels.Contact, Never> {
+        contactSubject.eraseToAnyPublisher()
+    }
 
-    var contactPublisher: AnyPublisher<XXModels.Contact, Never> { contactRelay.eraseToAnyPublisher() }
-    private let contactRelay = PassthroughSubject<XXModels.Contact, Never>()
+    var statePublisher: AnyPublisher<ScanStatus, Never> {
+        stateSubject.eraseToAnyPublisher()
+    }
 
-    var state: AnyPublisher<ScanViewState, Never> { stateRelay.eraseToAnyPublisher() }
-    private let stateRelay = CurrentValueSubject<ScanViewState, Never>(.init())
+    private let contactSubject = PassthroughSubject<XXModels.Contact, Never>()
+    private let stateSubject = CurrentValueSubject<ScanStatus, Never>(.reading)
 
     func resetScanner() {
-        stateRelay.value.status = .reading
+        stateSubject.send(.reading)
     }
 
     func didScanData(_ data: Data) {
-        guard stateRelay.value.status == .reading else { return }
-        stateRelay.value.status = .processing
-
-        backgroundScheduler.schedule { [weak self] in
-            guard let self = self else { return }
-
-            do {
-                guard let usernameAndId = try self.verifyScanned(data) else {
-                    self.stateRelay.value.status = .failed(.unknown(Localized.Scan.Error.general))
-                    return
-                }
-
-
-
-                if let previouslyAdded = try? self.database.fetchContacts(.init(id: [usernameAndId.1])).first {
-                    var error = ScanError.unknown(Localized.Scan.Error.general)
-
-                    switch previouslyAdded.authStatus {
-                    case .friend:
-                        error = .alreadyFriends(usernameAndId.0)
-                    case .requested, .verified:
-                        error = .requestOpened
-                    default:
-                        break
-                    }
-
-                    self.stateRelay.value.status = .failed(error)
-                    return
-                }
-
-                let facts = try? self.getFactsFromContact(data)
-                let contactEmail = facts?.first(where: { $0.type == FactType.email.rawValue })?.fact
-                let contactPhone = facts?.first(where: { $0.type == FactType.phone.rawValue })?.fact
-
-                let contact = Contact(
-                    id: usernameAndId.1,
-                    marshaled: data,
-                    username: usernameAndId.0,
-                    email: contactEmail,
-                    phone: contactPhone,
-                    nickname: nil,
-                    photo: nil,
-                    authStatus: .stranger,
-                    isRecent: false,
-                    createdAt: Date()
-                )
-
-                self.succeed(with: contact)
-            } catch {
-                self.stateRelay.value.status = .failed(.unknown(Localized.Scan.Error.invalid))
-            }
+        guard stateSubject.value == .reading else { return }
+        stateSubject.send(.processing)
+
+        let user = XXClient.Contact.live(data)
+
+        guard let uid = try? user.getId(),
+              let facts = try? user.getFacts(),
+              let username = facts.first(where: { $0.type == FactType.username.rawValue })?.fact else {
+            let errorTitle = Localized.Scan.Error.invalid
+            stateSubject.send(.failed(.unknown(errorTitle)))
+            return
         }
-    }
 
-    private func verifyScanned(_ data: Data) throws -> (String, Data)? {
-        let id = try? GetIdFromContact.live(data)
-        let facts = try? getFactsFromContact(data)
-        let username = facts?.first(where: { $0.type == FactType.username.rawValue })?.fact
+        let email = facts.first { $0.type == FactType.email.rawValue }?.fact
+        let phone = facts.first { $0.type == FactType.phone.rawValue }?.fact
 
-        guard let id = id, let username = username else { return nil }
-        return (username, id)
-    }
+        if let alreadyContact = try? database.fetchContacts(.init(id: [uid])).first {
+            if alreadyContact.isBlocked, reportingStatus.isEnabled() {
+                stateSubject.send(.failed(.unknown("You previously blocked this user.")))
+                return
+            }
+
+            if alreadyContact.isBanned, reportingStatus.isEnabled() {
+                stateSubject.send(.failed(.unknown("This user was banned.")))
+                return
+            }
+
+            if alreadyContact.authStatus == .friend {
+                stateSubject.send(.failed(.alreadyFriends(username)))
+            } else if [.requested, .verified].contains(alreadyContact.authStatus) {
+                stateSubject.send(.failed(.requestOpened))
+            } else {
+                let generalErrorTitle = Localized.Scan.Error.general
+                stateSubject.send(.failed(.unknown(generalErrorTitle)))
+            }
+
+            return
+        }
 
-    private func succeed(with contact: XXModels.Contact) {
-        stateRelay.value.status = .success
-        contactRelay.send(contact)
+        stateSubject.send(.success)
+        contactSubject.send(.init(
+            id: uid,
+            marshaled: data,
+            username: username,
+            email: email,
+            phone: phone,
+            nickname: nil,
+            photo: nil,
+            authStatus: .stranger,
+            isRecent: false,
+            createdAt: Date()
+        ))
     }
 }