diem/diem · error

expected same number of event lists as transactions, receive

Error message

expected same number of event lists as transactions, received {} event lists and {} transactions

What it means

In the same view-conversion code, after checking transaction_infos, the library verifies that the optional `events` field contains one event list per transaction. A `TransactionsWithProof` whose event_lists count differs from the transaction count cannot prove which events belong to which transaction, so the library rejects it rather than silently mis-associating events.

Source

Thrown at json-rpc/types/src/views.rs:885

            return Ok(Self::empty());
        }
        let start_version = txs
            .first_transaction_version
            .ok_or_else(|| format_err!("expected a start version since tx list non-empty"))?;

        let transactions = txs.transactions;
        let transaction_infos = txs.proof.transaction_infos;

        ensure!(
            transaction_infos.len() == transactions.len(),
            "expected same number of transaction_infos as transactions, \
             received {} transaction_infos and {} transactions",
            transaction_infos.len(),
            transactions.len(),
        );

        let event_lists = if let Some(event_lists) = txs.events {
            ensure!(
                event_lists.len() == transactions.len(),
                "expected same number of event lists as transactions, \
                 received {} event lists and {} transactions",
                event_lists.len(),
                transactions.len(),
            );
            event_lists
        } else {
            vec![Vec::new(); transactions.len()]
        };

        let tx_iter = transactions.into_iter();
        let infos_iter = transaction_infos.into_iter();
        let event_lists_iter = event_lists.into_iter();

        let iter = tx_iter.enumerate().zip(infos_iter).zip(event_lists_iter);

        let tx_list = iter

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Compare `events.as_ref().map(|e| e.len())` with `transactions.len()` before conversion and re-fetch if they differ
  2. Re-query the node for transactions with proof and events; the response is incomplete or corrupt
  3. If events are unnecessary, pass `None` (or use the non-events query variant) instead of a partially populated event list
  4. When building fixtures, generate event_lists from the same loop that generates transactions so counts always match
  5. Upgrade client/node to matching versions if the events proof format changed

Example fix

// before
let txs = TransactionsWithProof { transactions, events: Some(event_lists), proof };
let view = txs.try_into()?;
// after
if let Some(ev) = &event_lists {
    assert_eq!(ev.len(), transactions.len(), "event list count mismatch; re-fetch");
}
let txs = TransactionsWithProof { transactions, events: Some(event_lists), proof };
let view = txs.try_into()?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_events(txs: &TransactionsWithProof) -> Result<(), String> {
    if let Some(ev) = &txs.events {
        if ev.len() != txs.transactions.len() {
            return Err(format!("event lists ({}) != transactions ({})", ev.len(), txs.transactions.len()));
        }
    }
    Ok(())
}

Type guard

fn has_matching_event_lists(txs: &TransactionsWithProof) -> bool {
    match &txs.events {
        Some(ev) => ev.len() == txs.transactions.len(),
        None => true,
    }
}

Try / catch

match tx_view.try_into_transaction_with_proof() {
    Ok(verified) => verified,
    Err(e) if e.to_string().contains("expected same number of event lists") => {
        eprintln!("event list count mismatch, re-fetching");
        re_fetch_with_events()?  // returns the verified type
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Converting a `TransactionsWithProof` into the verified view when `txs.events` is `Some` but `event_lists.len() != transactions.len()` — e.g. a node response where events were truncated, or a manually built struct that attached events for only some transactions.

Common situations: Node bug or partially synced state returning event lists for a subset of transactions; protocol-version mismatch between client and server changing how events are batched; hand-written test data where events were populated for fewer/more entries than transactions.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/98f1207674c98fba. Report an issue: GitHub.