linera-io/linera-protocol · error
Query {argument:?} is invalid and could not be deserialized
Error message
Query {argument:?} is invalid and could not be deserialized What it means
The linera-sdk service entrypoint macro deserializes incoming query bytes with serde_json into the app's Query type before calling handle_query. Bytes that are not valid JSON for that type panic the service guest with 'Query ... is invalid and could not be deserialized'. The request reaches the application service through GraphQL queries against the chain.
Source
Thrown at linera-sdk/src/service/mod.rs:46
///
/// Generates the necessary boilerplate for implementing the service WIT interface, exporting the
/// necessary resource types and functions so that the host can call the application service.
#[macro_export]
macro_rules! service {
($service:ident) => {
#[doc(hidden)]
static mut SERVICE: Option<$service> = None;
/// Export the service interface.
$crate::export_service!($service with_types_in $crate::service::wit);
/// Mark the service type to be exported.
impl $crate::service::wit::exports::linera::app::service_entrypoints::Guest for $service {
fn handle_query(argument: Vec<u8>) -> Vec<u8> {
use $crate::util::BlockingWait as _;
$crate::ServiceLogger::install();
let request = $crate::serde_json::from_slice(&argument)
.unwrap_or_else(|_| panic!("Query {argument:?} is invalid and could not be deserialized"));
let response = $crate::service::run_async_entrypoint(
unsafe { &mut SERVICE },
move |service| service.handle_query(request).blocking_wait(),
);
$crate::serde_json::to_vec(&response)
.expect("Failed to serialize query response")
}
}
/// Stub of a `main` entrypoint so that the binary doesn't fail to compile on targets other
/// than WebAssembly.
#[cfg(not(target_arch = "wasm32"))]
fn main() {}
};
}
/// Runs an asynchronous entrypoint in a blocking manner, by repeatedly polling the entrypoint
/// future.View on GitHub (pinned to 6c226ddcb3)
Solutions
- Match the JSON exactly to the app's Query type: correct variant names, field names, and casing
- Test the serialization client-side first: serde_json::from_slice::<Query>(bytes) must succeed before sending
- For enum queries use the tagged form the app's serde attributes produce (e.g. {"variant":{...}})
- Update query senders whenever the app's Query type changes and is re-published
Example fix
// before (wrong shape for enum Query)
let bytes = br#"{"account": "0xab.."}"#;
// after (correct serde_enum tagged form)
let bytes = serde_json::to_vec(&Query::Balance { owner })?; // e.g. {"balance":{"owner":"0xab.."}} Defensive patterns
Strategy: validation
Validate before calling
// Client-side, before sending a query to the service:
let payload = serde_json::to_string(&query)?;
serde_json::from_str::<app::Query>(&payload)
.expect("payload must round-trip as the app's Query type");
// now safe to submit via GraphQL Prevention
- Generate query payloads with serde from the app's Query type
- Respect the app's serde casing/tag attributes when constructing JSON by hand
- Log the exact payload when a query fails so mismatches are diffable against the ABI
When it happens
Trigger: Sending a GraphQL query (chain application service query) whose argument string is not valid JSON for the app's declared Query type: wrong field names/types, extra/missing fields, or an entirely different shape (e.g. reusing an operation-style argument for a query).
Common situations: Frontends sending snake_case where the app's serde config expects camelCase (or vice versa); querying a newly published app with arguments designed for its previous version; examples like fungible/counters where each app has its own Query enum variants.
Related errors
- Failed to deserialize instantiation argument {argument:?}
- Failed to deserialize service response
- Application parameters must be deserializable
- Failed to deserialize query response from application
- Attempt to modify storage from a service
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/1e9e2793aea458b6.
Report an issue: GitHub.