diff --git a/ipa-core/src/helpers/transport/handler.rs b/ipa-core/src/helpers/transport/handler.rs
index 736a25c94..0f56eb035 100644
--- a/ipa-core/src/helpers/transport/handler.rs
+++ b/ipa-core/src/helpers/transport/handler.rs
@@ -27,11 +27,18 @@ use crate::{
     },
 };
 
+/// Represents some response sent from MPC helper acting on a given request. It is rudimental now
+/// because we sent everything as HTTP body, but it could evolve.
+///
+/// ## Performance
+/// This implementation is far from being optimal. Between HTTP and transport layer, there exists
+/// one round of serialization and deserialization to properly represent the types. It is not critical
+/// to address, because MPC helpers have to handle a constant number of requests per query. Note
+/// that all requests tagged with [`crate::helpers::transport::RouteId::Records`] are not routed
+/// through [`RequestHandler`], so there is no penalty.
+///
 pub struct HelperResponse {
     body: Vec<u8>,
-    // Empty,
-    // QueryCreated(QueryId),
-    // QueryStatus(QueryStatus),
 }
 
 impl Debug for HelperResponse {
@@ -41,6 +48,7 @@ impl Debug for HelperResponse {
 }
 
 impl HelperResponse {
+    /// Returns
     pub fn ok() -> Self {
         Self { body: Vec::new() }
     }
@@ -49,14 +57,8 @@ impl HelperResponse {
         self.body
     }
 
-    pub fn into_owned<T: DeserializeOwned>(self) -> T {
-        serde_json::from_slice(&self.body).unwrap_or_else(|e| {
-            panic!(
-                "Failed to deserialize {:?} into {}: {e}",
-                &self.body,
-                type_name::<T>()
-            )
-        })
+    pub fn try_into_owned<T: DeserializeOwned>(self) -> Result<T, serde_json::Error> {
+        serde_json::from_slice(&self.body)
     }
 }
 
diff --git a/ipa-core/src/helpers/transport/in_memory/transport.rs b/ipa-core/src/helpers/transport/in_memory/transport.rs
index 0ce41eabc..a58de4b55 100644
--- a/ipa-core/src/helpers/transport/in_memory/transport.rs
+++ b/ipa-core/src/helpers/transport/in_memory/transport.rs
@@ -124,7 +124,6 @@ impl<I: TransportIdentity> InMemoryTransport<I> {
                                         ),
                                     )
                                     .await
-                                // callbacks.handle(Clone::clone(&this), addr).await
                             }
                         };
 
diff --git a/ipa-core/src/net/http_serde.rs b/ipa-core/src/net/http_serde.rs
index 012f9b6c5..2937c948a 100644
--- a/ipa-core/src/net/http_serde.rs
+++ b/ipa-core/src/net/http_serde.rs
@@ -229,9 +229,11 @@ pub mod query {
             pub query_id: QueryId,
         }
 
-        impl From<HelperResponse> for ResponseBody {
-            fn from(value: HelperResponse) -> Self {
-                value.into_owned()
+        impl TryFrom<HelperResponse> for ResponseBody {
+            type Error = serde_json::Error;
+
+            fn try_from(value: HelperResponse) -> Result<Self, Self::Error> {
+                value.try_into_owned()
             }
         }
 
diff --git a/ipa-core/src/net/server/handlers/query/create.rs b/ipa-core/src/net/server/handlers/query/create.rs
index 9edc729f2..a1cbd1217 100644
--- a/ipa-core/src/net/server/handlers/query/create.rs
+++ b/ipa-core/src/net/server/handlers/query/create.rs
@@ -21,7 +21,9 @@ async fn handler(
         .dispatch(req.query_config, BodyStream::empty())
         .await
     {
-        Ok(resp) => Ok(Json(resp.into())),
+        Ok(resp) => {
+            Ok(Json(resp.try_into()?))
+        },
         Err(err @ NewQuery(NewQueryError::State { .. })) => {
             Err(Error::application(StatusCode::CONFLICT, err))
         }