diff --git a/native/account/log-in-panel.react.js b/native/account/log-in-panel.react.js
--- a/native/account/log-in-panel.react.js
+++ b/native/account/log-in-panel.react.js
@@ -340,7 +340,7 @@
       const messageForException = getMessageForException(e);
       if (
         messageForException === 'user_not_found' ||
-        messageForException === 'login failed'
+        messageForException === 'login_failed'
       ) {
         Alert.alert(
           userNotFoundAlertDetails.title,
diff --git a/native/profile/delete-account.react.js b/native/profile/delete-account.react.js
--- a/native/profile/delete-account.react.js
+++ b/native/profile/delete-account.react.js
@@ -77,7 +77,7 @@
         await deleteNativeCredentialsFor();
         return await callDeleteAccount(password);
       } catch (e) {
-        if (getMessageForException(e) === 'login failed') {
+        if (getMessageForException(e) === 'login_failed') {
           Alert.alert(
             'Incorrect password',
             'The password you entered is incorrect',
diff --git a/services/identity/src/constants.rs b/services/identity/src/constants.rs
--- a/services/identity/src/constants.rs
+++ b/services/identity/src/constants.rs
@@ -263,6 +263,11 @@
   pub const KEYSERVER_NOT_FOUND: &str = "keyserver_not_found";
   pub const PASSWORD_USER: &str = "password_user";
   pub const INVALID_MESSAGE: &str = "invalid_message";
+  pub const INVALID_MESSAGE_FORMAT: &str = "invalid_message_format";
+  pub const MISSING_PLATFORM_OR_CODE_VERSION_METADATA: &str =
+    "missing_platform_or_code_version_metadata";
+  pub const MISSING_KEY: &str = "missing_key";
+  pub const MESSAGE_NOT_AUTHENTICATED: &str = "message_not_authenticated";
 }
 
 // Tunnelbroker
diff --git a/services/identity/src/device_list.rs b/services/identity/src/device_list.rs
--- a/services/identity/src/device_list.rs
+++ b/services/identity/src/device_list.rs
@@ -231,14 +231,14 @@
   if device_list.last_primary_signature.is_some() {
     debug!("Received lastPrimarySignature for initial device list");
     return Err(Status::invalid_argument(
-      "invalid device list: unexpected lastPrimarySignature",
+      tonic_status_messages::INVALID_DEVICE_LIST_UPDATE,
     ));
   }
 
   let Some(signature) = &device_list.current_primary_signature else {
     debug!("Missing curPrimarySignature for initial device list");
     return Err(Status::invalid_argument(
-      "invalid device list: signature missing",
+      tonic_status_messages::INVALID_DEVICE_LIST_UPDATE,
     ));
   };
 
@@ -251,7 +251,7 @@
   if device_list.devices.len() != 1 {
     debug!("Invalid device list length");
     return Err(Status::invalid_argument(
-      "invalid device list: invalid length",
+      tonic_status_messages::INVALID_DEVICE_LIST_UPDATE,
     ));
   }
 
@@ -263,7 +263,7 @@
   {
     debug!("Invalid primary device ID for initial device list");
     return Err(Status::invalid_argument(
-      "invalid device list: invalid primary device",
+      tonic_status_messages::INVALID_DEVICE_LIST_UPDATE,
     ));
   }
 
diff --git a/services/identity/src/grpc_services/shared.rs b/services/identity/src/grpc_services/shared.rs
--- a/services/identity/src/grpc_services/shared.rs
+++ b/services/identity/src/grpc_services/shared.rs
@@ -2,7 +2,9 @@
 use tonic::{Request, Status};
 use tracing::trace;
 
-use crate::constants::{request_metadata, MIN_SUPPORTED_NATIVE_VERSION};
+use crate::constants::{
+  request_metadata, tonic_status_messages, MIN_SUPPORTED_NATIVE_VERSION,
+};
 
 pub use grpc_clients::identity::shared::PlatformMetadata;
 
@@ -37,7 +39,9 @@
   req: &Request<T>,
 ) -> Result<PlatformMetadata, Status> {
   let (code_version, device_type) = get_version_info(req).ok_or_else(|| {
-    Status::invalid_argument("missing platform or code version metadata")
+    Status::invalid_argument(
+      tonic_status_messages::MISSING_PLATFORM_OR_CODE_VERSION_METADATA,
+    )
   })?;
   let state_version = get_value(req, request_metadata::STATE_VERSION)
     .and_then(|it| it.parse().ok());
diff --git a/services/identity/src/reserved_users.rs b/services/identity/src/reserved_users.rs
--- a/services/identity/src/reserved_users.rs
+++ b/services/identity/src/reserved_users.rs
@@ -31,8 +31,9 @@
   expected_statement: &[u8],
 ) -> Result<Message<T>, Status> {
   let deserialized_message: Message<T> =
-    serde_json::from_str(keyserver_message)
-      .map_err(|_| Status::invalid_argument("message format invalid"))?;
+    serde_json::from_str(keyserver_message).map_err(|_| {
+      Status::invalid_argument(tonic_status_messages::INVALID_MESSAGE_FORMAT)
+    })?;
 
   if !constant_time_eq(
     deserialized_message.statement.as_bytes(),
@@ -43,10 +44,10 @@
     ));
   }
 
-  let issued_at: DateTime<Utc> = deserialized_message
-    .issued_at
-    .parse()
-    .map_err(|_| Status::invalid_argument("message format invalid"))?;
+  let issued_at: DateTime<Utc> =
+    deserialized_message.issued_at.parse().map_err(|_| {
+      Status::invalid_argument(tonic_status_messages::INVALID_MESSAGE_FORMAT)
+    })?;
 
   let now = Utc::now();
   if (now - issued_at).num_seconds() > 5 {
@@ -55,10 +56,10 @@
     ));
   }
 
-  let public_key_string = CONFIG
-    .keyserver_public_key
-    .as_deref()
-    .ok_or_else(|| Status::failed_precondition("missing key"))?;
+  let public_key_string =
+    CONFIG.keyserver_public_key.as_deref().ok_or_else(|| {
+      Status::failed_precondition(tonic_status_messages::MISSING_KEY)
+    })?;
 
   crate::grpc_utils::ed25519_verify(
     public_key_string,
diff --git a/services/identity/src/siwe.rs b/services/identity/src/siwe.rs
--- a/services/identity/src/siwe.rs
+++ b/services/identity/src/siwe.rs
@@ -51,7 +51,7 @@
         errorType = error_types::SIWE_LOG,
         "Signature verification failed: {}", e
       );
-      Status::unauthenticated("message not authenticated")
+      Status::unauthenticated(tonic_status_messages::MESSAGE_NOT_AUTHENTICATED)
     })?;
 
   Ok(siwe_message)
diff --git a/services/identity/src/tunnelbroker.rs b/services/identity/src/tunnelbroker.rs
--- a/services/identity/src/tunnelbroker.rs
+++ b/services/identity/src/tunnelbroker.rs
@@ -12,7 +12,7 @@
 use crate::constants::error_types;
 use crate::error::Error;
 
-pub async fn create_tunnelbroker_client(
+async fn create_tunnelbroker_client(
 ) -> Result<TunnelbrokerServiceClient<Channel>, Error> {
   shared_tb_client(&CONFIG.tunnelbroker_endpoint)
     .await
diff --git a/shared/comm-opaque2/src/error.rs b/shared/comm-opaque2/src/error.rs
--- a/shared/comm-opaque2/src/error.rs
+++ b/shared/comm-opaque2/src/error.rs
@@ -36,12 +36,12 @@
 
 fn protocol_error_to_js_error(error: ProtocolError) -> JsError {
   match error {
-    ProtocolError::IdentityGroupElementError => JsError::new("server error"),
-    ProtocolError::InvalidLoginError => JsError::new("login failed"),
-    ProtocolError::LibraryError(_) => JsError::new("internal error"),
+    ProtocolError::IdentityGroupElementError => JsError::new("server_error"),
+    ProtocolError::InvalidLoginError => JsError::new("login_failed"),
+    ProtocolError::LibraryError(_) => JsError::new("internal_error"),
     ProtocolError::ReflectedValueError => {
-      JsError::new("invalid server response")
+      JsError::new("invalid_server_response")
     }
-    ProtocolError::SerializationError => JsError::new("invalid argument"),
+    ProtocolError::SerializationError => JsError::new("invalid_argument"),
   }
 }
diff --git a/shared/comm-opaque2/src/grpc.rs b/shared/comm-opaque2/src/grpc.rs
--- a/shared/comm-opaque2/src/grpc.rs
+++ b/shared/comm-opaque2/src/grpc.rs
@@ -11,23 +11,23 @@
   match error {
     ProtocolError::IdentityGroupElementError => {
       info!("Failed to validate password");
-      Status::aborted("server error")
+      Status::aborted("server_error")
     }
     ProtocolError::InvalidLoginError => {
       info!("Failed to login");
-      Status::aborted("login failed")
+      Status::aborted("login_failed")
     }
     ProtocolError::LibraryError(_) => {
       info!("Opaque error");
-      Status::invalid_argument("internal error")
+      Status::invalid_argument("internal_error")
     }
     ProtocolError::ReflectedValueError => {
       info!("OPRF value was reflected");
-      Status::invalid_argument("invalid server response")
+      Status::invalid_argument("invalid_server_response")
     }
     ProtocolError::SerializationError => {
       info!("Invalid argument");
-      Status::invalid_argument("invalid argument")
+      Status::invalid_argument("invalid_argument")
     }
   }
 }
diff --git a/shared/grpc_clients/src/identity/authenticated.rs b/shared/grpc_clients/src/identity/authenticated.rs
--- a/shared/grpc_clients/src/identity/authenticated.rs
+++ b/shared/grpc_clients/src/identity/authenticated.rs
@@ -21,11 +21,8 @@
 
 impl ToMetadataValueAscii for str {
   fn parse_to_ascii(&self) -> Result<MetadataValue<Ascii>, Status> {
-    self.parse().map_err(|e: InvalidMetadataValue| {
-      Status::invalid_argument(format!(
-        "Non-Ascii character present in metadata value: {}",
-        e
-      ))
+    self.parse().map_err(|_: InvalidMetadataValue| {
+      Status::invalid_argument("non_ascii_character_in_metadata_value")
     })
   }
 }
diff --git a/shared/grpc_clients/src/identity/shared.rs b/shared/grpc_clients/src/identity/shared.rs
--- a/shared/grpc_clients/src/identity/shared.rs
+++ b/shared/grpc_clients/src/identity/shared.rs
@@ -68,11 +68,8 @@
   fn parse_to_ascii(&self) -> Result<MetadataValue<Ascii>, Status> {
     let ascii_string = self.to_string();
 
-    ascii_string.parse().map_err(|e: InvalidMetadataValue| {
-      Status::invalid_argument(format!(
-        "Non-Ascii character present in metadata value: {}",
-        e
-      ))
+    ascii_string.parse().map_err(|_: InvalidMetadataValue| {
+      Status::invalid_argument("non_ascii_character_in_metadata_value")
     })
   }
 }
diff --git a/web/account/traditional-login-form.react.js b/web/account/traditional-login-form.react.js
--- a/web/account/traditional-login-form.react.js
+++ b/web/account/traditional-login-form.react.js
@@ -129,7 +129,7 @@
       const messageForException = getMessageForException(e);
       if (
         messageForException === 'user_not_found' ||
-        messageForException === 'login failed'
+        messageForException === 'login_failed'
       ) {
         setErrorMessage('incorrect username or password');
       } else if (