linera-io/linera-protocol · error
Failed to deserialize query response from application
Error message
Failed to deserialize query response from application
What it means
ServiceRuntime::query_application forwards a JSON query to another application through the host (service_wit::try_query_application) and parses the returned bytes with serde_json::from_slice::<A::QueryResponse>. The expect panics when the target application's query response does not decode into the type the caller compiled against.
Source
Thrown at linera-sdk/src/service/runtime.rs:218
.expect("Failed to serialize application operation");
service_wit::schedule_operation(&bytes);
}
/// Queries another application.
pub fn query_application<A: ServiceAbi>(
&self,
application: ApplicationId<A>,
query: &A::Query,
) -> A::QueryResponse {
let query_bytes =
serde_json::to_vec(&query).expect("Failed to serialize query to another application");
let response_bytes =
service_wit::try_query_application(application.forget_abi().into(), &query_bytes);
serde_json::from_slice(&response_bytes)
.expect("Failed to deserialize query response from application")
}
}
impl<Application> ServiceRuntime<Application>
where
Application: Service,
{
/// Loads a value from the `slot` cache or fetches it and stores it in the cache.
fn fetch_value_through_cache<T>(slot: &Mutex<Option<T>>, fetch: impl FnOnce() -> T) -> T
where
T: Clone,
{
let mut value = slot
.lock()
.expect("Mutex should never be poisoned because service runs in a single thread");
if value.is_none() {
*value = Some(fetch());View on GitHub (pinned to 6c226ddcb3)
Solutions
- Align versions: rebuild the querying service against the exact crate version of the target application that is deployed, then restart the service
- Validate the raw response first during debugging: log serde_json::from_slice::<serde_json::Value>(&response_bytes) to see the actual shape the peer returned
- Make the caller's QueryResponse tolerant (Option fields, #[serde(default)], ignore unknown keys) for forward compatibility
- Check that application_id comes from the same publish/genesis as the deployed target, not from a config file of a previous network
Example fix
// before: panic on any drift
let res: TokenResponse = runtime.query_application(app_id, q).await;
// after (debug path): inspect then decode with a clear message
let bytes = ...; // response bytes
let value: serde_json::Value = serde_json::from_slice(&bytes)
.expect("peer returned non-JSON");
let res: TokenResponse = serde_json::from_value(value)
.unwrap_or_else(|e| panic!("token app response schema mismatch: {e}")); Defensive patterns
Strategy: validation
Validate before calling
// Decode defensively via serde_json::Value first when peers are versioned. let v: serde_json::Value = serde_json::from_slice(&response_bytes).map_err(QueryError::BadJson)?; let r: A::QueryResponse = serde_json::from_value(v).map_err(QueryError::SchemaMismatch)?;
Prevention
- Pin peer application crates to exact versions and republish together
- Keep an integration test that queries a locally-instantiated peer service and asserts the decoded QueryResponse
- Design QueryResponse additively: new fields optional, old fields never renamed
- Surface schema-mismatch errors as application errors instead of letting the runtime panic take down the node service
When it happens
Trigger: Calling query_application::<OtherApp>(application_id, query) where the deployed OtherApp returns JSON not matching the caller's QueryResponse — version drift between modules, wrong application_id, or a response schema change (field rename, nesting, Option/required flip).
Common situations: Running a proxy/composed service (e.g. a wrapper app querying a token app) after the inner app was upgraded to a new response format; querying an application whose query handler errors and returns an error body instead of the expected payload; mixing module versions across testnet resets.
Related errors
- Failed to deserialize service response
- Application parameters must be deserializable
- Failed to deserialize instantiation argument {argument:?}
- Query {argument:?} is invalid and could not be deserialized
- Application parameters must be deserializable
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/183451f5a0f39132.
Report an issue: GitHub.