linera-io/linera-protocol · error · async_graphql::Error
invalid {label} hex: {e}
Error message
invalid {label} hex: {e} What it means
decode_hex is the shared helper the EVM bridge service uses to hex-decode GraphQL arguments (with optional 0x prefix) for decode_hex_array and process_deposit. It fails whenever hex::decode rejects the input: a non-hex character, an odd number of hex digits, or stray characters such as whitespace, quotes, or underscores. The message names which label (argument) failed and echoes the hex::decode cause.
Source
Thrown at linera-bridge/contracts/evm-bridge/src/service.rs:72
}
async fn handle_query(&self, request: Request) -> Response {
let schema = Schema::build(
self.clone(),
MutationRoot {
runtime: self.runtime.clone(),
},
EmptySubscription,
)
.finish();
schema.execute(request).await
}
}
/// Decodes a hex string (optional `0x` prefix) into bytes.
fn decode_hex(label: &str, s: &str) -> async_graphql::Result<Vec<u8>> {
hex::decode(s.strip_prefix("0x").unwrap_or(s))
.map_err(|e| async_graphql::Error::new(format!("invalid {label} hex: {e}")))
}
/// Decodes a hex string into a fixed-size byte array.
fn decode_hex_array<const N: usize>(label: &str, s: &str) -> async_graphql::Result<[u8; N]> {
decode_hex(label, s)?.as_slice().try_into().map_err(|_| {
async_graphql::Error::new(format!(
"{label} must be exactly {N} bytes ({} hex chars)",
N * 2
))
})
}
/// GraphQL mutation root: schedules bridge operations submitted by a client (the
/// demo UI, an admin tool, or a custom relayer). The application bytecode — and
/// thus this interface — cannot change after deployment, so every
/// [`BridgeOperation`] is exposed; on-chain authorization still gates each.
/// Byte-array arguments are hex-encoded strings (with or without `0x`).
pub struct MutationRoot {View on GitHub (pinned to 6c226ddcb3)
Solutions
- Send only even-length hex digits [0-9a-f] (case-insensitive) with at most one leading 0x prefix; re-copy the value from its source (transaction receipt, event log).
- Strip whitespace/newlines and any duplicate 0x prefix before sending; check for shell quoting issues ("$…" expansion, smart quotes).
- If the value is a decimal or other encoding, convert it to hex first (e.g. `cast --to-hex`, `toHex`), keeping the required byte length in mind.
Example fix
// before process_deposit(depositId: "0x12g4") // 'g' is not a hex digit -> invalid depositId hex // after process_deposit(depositId: "0x12f4") // even-length [0-9a-f] digits only
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_hex_arg(s: &str) -> bool {
let body = s.strip_prefix("0x").unwrap_or(s);
!body.is_empty() && body.len() % 2 == 0 && body.bytes().all(|b| b.is_ascii_hexdigit())
} Type guard
fn is_valid_hex(s: &str) -> bool {
let body = s.strip_prefix("0x").unwrap_or(s).trim();
!body.is_empty() && body.len() % 2 == 0 && body.bytes().all(|b| b.is_ascii_hexdigit())
} Prevention
- Validate hex args client-side (regex ^0x[0-9a-fA-F]*$ plus even length) before sending the GraphQL request.
- Copy hashes straight from the transaction receipt/event log rather than retyping them.
- Normalize once at the edge: strip whitespace and duplicate 0x prefixes in a single helper used by all callers.
When it happens
Trigger: Sending a GraphQL query/mutation to the evm-bridge service (e.g. process_deposit, or any arg decoded through decode_hex_array) where the argument contains characters outside [0-9a-fA-F] (after an optional 0x prefix), has odd length, or includes whitespace/newlines/quotes from shell or JSON copy-paste.
Common situations: Pasting an ENS name, decimal amount, or base58 value where a hex hash is expected; a truncated or double-prefixed hash ("0x0x…"); values copied from logs that include quotes or trailing whitespace; sending the same string to both keccak-decoded and hex-decoded fields and only one being valid hex.
Related errors
- {label} must be exactly {N} bytes ({} hex chars)
- invalid hex
- This user has no chain yet
- Request processing was cancelled
- There are {} owners but {} weights.
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/0413e6e7d7c39ec3.
Report an issue: GitHub.