linera-io/linera-protocol · error
expected 224 bytes of event data (7 x 32), got {}
Error message
expected 224 bytes of event data (7 x 32), got {} What it means
parse_deposit_event expects log.data to be exactly 224 bytes: seven ABI-encoded 32-byte words (source_chain_id, target_chain_id, target_application_id, target_account_owner, token, amount, nonce). The ensure at linera-bridge/src/proof/mod.rs:440 fails when the data section length differs, which means the non-indexed parameter list of the emitted event does not match the 7-field layout the parser was built for. Because topic[0] already matched, this is an event-shape mismatch, not a routing problem.
Source
Thrown at linera-bridge/src/proof/mod.rs:440
/// The `depositor` field is indexed (stored in `topics[1]`); all other parameters are
/// non-indexed and encoded in the log data.
pub fn parse_deposit_event(log: &ReceiptLog, expected_emitter: Address) -> Result<DepositEvent> {
ensure!(
log.address == expected_emitter,
"log emitter {:?} does not match expected bridge contract {:?}",
log.address,
expected_emitter
);
ensure!(
log.topics.first() == Some(&deposit_event_signature()),
"event topic does not match DepositInitiated signature"
);
ensure!(
log.topics.len() == 2,
"expected exactly 2 topics (signature + indexed depositor), got {}",
log.topics.len()
);
ensure!(
log.data.len() == 224,
"expected 224 bytes of event data (7 x 32), got {}",
log.data.len()
);
// Indexed `depositor` is in topics[1], left-padded to 32 bytes.
let depositor_topic = log.topics[1];
ensure!(
depositor_topic.as_slice()[..12] == [0u8; 12],
"invalid ABI encoding: depositor topic padding bytes (0..12) must be zero"
);
let depositor = Address::from_slice(&depositor_topic.as_slice()[12..32]);
let d = &log.data;
// ABI encodes addresses as left-padded 32-byte words; the first 12 bytes must be zero.
ensure!(
d[128..140] == [0u8; 12],View on GitHub (pinned to 6c226ddcb3)
Solutions
- Dump log.data.len() for the failing log and divide by 32 to see how many words the contract actually emitted.
- Diff the contract's current ABI against the 7 fields the parser decodes at d[0..224]; update the offsets and the 224 constant together if the ABI legitimately changed.
- Check whether a field was moved between indexed (topics) and non-indexed (data): if so, error 180 fires too — fix both sides in one change.
- Regenerate test fixtures (build_deposit_event_data) from the new ABI so tests encode the same shape the parser accepts.
Example fix
// before
ensure!(log.data.len() == 224, "expected 224 bytes of event data (7 x 32), got {}", log.data.len());
// after (ABI now carries 8 non-indexed words)
ensure!(log.data.len() == 256, "expected 256 bytes of event data (8 x 32), got {}", log.data.len());
// ...and extend the field extraction below to cover d[224..256] Defensive patterns
Strategy: validation
Validate before calling
fn has_deposit_data_shape(log: &ReceiptLog) -> bool {
log.topics.first() == Some(&deposit_event_signature())
&& log.topics.len() == 2
&& log.data.len() == 224 // 7 x 32-byte ABI words
}
if !has_deposit_data_shape(&log) {
tracing::warn!(len = log.data.len(), "skipping DepositInitiated-shaped log with wrong data size");
continue;
}
let event = parse_deposit_event(&log, bridge_addr)?; Try / catch
match parse_deposit_event(&log, bridge_addr) {
Ok(ev) => Some(ev),
Err(e) if e.to_string().contains("expected 224 bytes") => {
tracing::warn!(data_len = log.data.len(), "ABI drift suspected; skipping log");
None
}
Err(e) => { tracing::error!(error = %e, "deposit parse failed"); None }
} Prevention
- Add an ABI-compatibility assertion (expected data length constant) shared by tests and parser.
- Failing this check right after a contract upgrade means the parser is stale: update offsets in the same commit as the ABI change.
- Log the observed length to classify one-word-added vs field-moved changes quickly.
- Never widen the check silently; a wrong-size decode means wrong offsets and corrupted deposits.
When it happens
Trigger: A DepositInitiated event with an added or removed non-indexed parameter (e.g., a metadata string or extra fee field) so data is no longer 7*32 bytes; a test fixture that packs the wrong number of words via build_deposit_event_data; a contract upgrade that switched a field to indexed (shrinking data to 6 words while growing topics).
Common situations: Contract redeployed with a richer event but scanner still runs old parser; test helpers and parser drift out of sync after an ABI edit; decoding an analogous event (e.g., WithdrawalInitiated) that shares topic[0] by coincidence of signature hashing; chain with non-standard receipt encoding feeding evm_scan_iteration.
Related errors
- expected exactly 2 topics (signature + indexed depositor), g
- invalid ABI encoding: depositor topic padding bytes (0..12)
- invalid ABI encoding: address padding bytes (128..140) must
- topics must be an RLP list
- log data must be a byte string, not a list
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/55abf3312f2d7b59.
Report an issue: GitHub.