linera-io/linera-protocol · critical · ExecutionError
OracleResponseMismatch
OracleResponseMismatch
Error message
ExecutionError::OracleResponseMismatch
What it means
Linera records every oracle response (cross-chain balance reads, blob reads, etc.) when a block is first executed, and replays them when the block is re-executed by validators or workers. TransactionTracker::replay_oracle_response compares each freshly produced response against the next recorded one; OracleResponseMismatch means the same transaction produced a different oracle answer than the one recorded in the proposal or certificate.
Source
Thrown at linera-execution/src/transaction_tracker.rs:339
first_index,
next_index,
}
},
)
.collect();
(app_id, updates)
})
.collect()
}
/// Adds the oracle response to the record.
/// If replaying, it also checks that it matches the next replayed one and returns `true`.
pub fn replay_oracle_response(
&mut self,
oracle_response: OracleResponse,
) -> Result<bool, ExecutionError> {
let replaying = if let Some(recorded_response) = self.next_replayed_oracle_response()? {
ensure!(
recorded_response == oracle_response,
ExecutionError::OracleResponseMismatch
);
true
} else {
false
};
self.oracle_responses.push(oracle_response);
Ok(replaying)
}
/// If in replay mode, returns the next oracle response, or an error if it is missing.
///
/// If not in replay mode, `None` is returned, and the caller must execute the actual oracle
/// to obtain the value.
///
/// In both cases, the value (returned or obtained from the oracle) must be recorded using
/// `add_oracle_response`.View on GitHub (pinned to 6c226ddcb3)
Solutions
- Make application oracle reads deterministic: never branch on wall-clock time, randomness, or remote-chain state read outside the recorded oracle
- Verify that all executing nodes hold the same view of the referenced chain/blob (sync storage, check pruning policy)
- If you maintain a worker or custom client, treat this error as a reason to reject the block or certificate, not retry it, then re-download state from a committee validator
- Check for version skew between proposer and validator: the oracle response encoding has changed across Linera versions
Example fix
// before
let matched = tracker.replay_oracle_response(response)?; // mismatch aborts with no context
// after
match tracker.replay_oracle_response(response) {
Ok(replaying) => { /* continue */ }
Err(ExecutionError::OracleResponseMismatch) => {
// deterministic divergence: reject the block, do not retry
return Err(anyhow::anyhow!("oracle divergence on block replay"));
}
Err(e) => return Err(e.into()),
} Defensive patterns
Strategy: try-catch
Try / catch
Match ExecutionError::OracleResponseMismatch explicitly around replay_oracle_response / execute_transaction calls. It is a deterministic divergence, not a transient fault: reject or quarantine the block, resynchronize state from a committee validator, and never retry the same replay against the same data.
Prevention
- Design applications so all cross-chain and blob reads go through recorded oracle queries and return identical results on every node
- Keep proposers and validators on the same Linera protocol version
- Ensure blob storage and pruning policies are identical across executing nodes
When it happens
Trigger: Re-executing a block via handle_request, apply_checkpoint, or blob_used where an oracle query (e.g. the balance of another chain, a blob's content) now returns a value different from the one recorded when the block was proposed and signed.
Common situations: Non-deterministic application logic that reads remote state which changed between proposal and validation; two executing nodes holding different views of the same cross-chain state; pruned or rewritten blobs; a malicious proposer fabricating oracle responses.
Related errors
- UnexpectedOracleResponse
- no signer found for owner ${owner}
- CannotRejectMessage
- Certificate justification commitment does not match its just
- Certificate unlocking round does not match the top of its ju
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/55e6ee320eac7ef8.
Report an issue: GitHub.