linera-io/linera-protocol · critical · ExecutionError
UnexpectedOracleResponse
UnexpectedOracleResponse
Error message
ExecutionError::UnexpectedOracleResponse
What it means
During replay, TransactionTracker holds the list of oracle responses recorded when the block was first executed. into_outcome verifies that this list is fully consumed; UnexpectedOracleResponse means the recorded list still had responses left over — the re-execution performed fewer oracle queries than were originally recorded.
Source
Thrown at linera-execution/src/transaction_tracker.rs:392
local_time: _,
transaction_index: _,
next_application_index,
next_chain_index,
events,
blobs,
previously_created_blobs: _,
operation_result,
streams_to_process,
blobs_published,
free_blob_ids,
prepared_checkpoint: _,
} = self;
ensure!(
streams_to_process.is_empty(),
ExecutionError::UnprocessedStreams
);
if let Some(mut responses) = replaying_oracle_responses {
ensure!(
responses.next().is_none(),
ExecutionError::UnexpectedOracleResponse
);
}
let blobs = blobs
.into_iter()
.map(|(blob_id, content)| Blob::new_with_hash_unchecked(blob_id, content))
.collect::<Vec<_>>();
Ok(TransactionOutcome {
outgoing_messages,
oracle_responses,
next_application_index,
next_chain_index,
events,
blobs,
operation_result: operation_result.unwrap_or_default(),
blobs_published,
free_blob_ids,View on GitHub (pinned to 6c226ddcb3)
Solutions
- Recompile/redeploy so the replayed block executes the exact bytecode it was recorded with (the published blob must match)
- Discard the stale checkpoint and re-download blocks and recorded responses from a committee validator
- Audit the application for conditional oracle reads (a branch that sometimes skips a query) and make read patterns stable per code path
Defensive patterns
Strategy: try-catch
Try / catch
Match ExecutionError::UnexpectedOracleResponse alongside OracleResponseMismatch around replay and checkpoint-apply calls. Both indicate replay divergence: halt the replay, discard the checkpoint, resynchronize from a validator, and re-validate rather than continuing.
Prevention
- Never change application bytecode while historical blocks still need replay
- Take checkpoints only at block boundaries where recorded oracle responses are consistent
- Keep oracle read patterns deterministic and unconditional per code path
When it happens
Trigger: Replaying a block whose execution path skipped an oracle query the original run performed — usually because application code or state changed between the recorded run and the replay, or a checkpoint was applied (apply_checkpoint) with a stale response list.
Common situations: Changing WASM application bytecode while historical blocks still need replay; replaying from a checkpoint whose recorded oracle responses no longer line up with the replayed transactions; non-deterministic control flow that conditionally skips oracle reads.
Related errors
- OracleResponseMismatch
- Checkpoint precondition failed: Checkpoint must be the first
- Checkpoint precondition failed: chain has consumed system ev
- InternalError
- Incorrect ApplicationId
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/a1e60b64b4dc8172.
Report an issue: GitHub.