nautechsystems/nautilus_trader · error
Verified decision block {} has no base fee
Error message
Verified decision block {} has no base fee What it means
After verifying the decision block header, the client requires `base_fee_per_gas` to compute EIP-1559 max fee/priority fee. If the verified header carries no base fee (None), fee derivation is impossible, so the client aborts the pre-sign flow naming the offending block number.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:2342
);
}
let decision_ancestry = self.verify_decision_ancestry(decision_header).await?;
validate_transaction_authorization(authorization, to, value, &input)?;
let deployment_verification = required_verification(
self.verification
.verify_deployment_manifest(&self.deployment_manifest, decision_header.number)
.await,
"pre-sign deployment manifest",
)?;
let authorization_decisions = match authorization {
Some(authorization) => {
self.verify_transaction_authorization(authorization, decision_header.number)
.await?
}
None => Vec::new(),
};
let base_fee_per_gas_wei = decision_header.base_fee_per_gas.ok_or_else(|| {
anyhow::anyhow!(
"Verified decision block {} has no base fee",
decision_header.number
)
})?;
let priority_fee_verification = required_verification(
self.verification.verify_priority_fee().await,
"pre-sign priority fee",
)?;
let priority_fee_per_gas_wei = priority_fee_verification.value;
let (max_fee_per_gas, max_priority_fee_per_gas) = derive_fees(
base_fee_per_gas_wei,
priority_fee_per_gas_wei,
self.base_fee_buffer_bps,
u128::from(self.max_fee_per_gas_wei),
)?;
let gas_estimate_verification = required_verification(
self.verification
.verify_gas_estimate(View on GitHub (pinned to 18893faf8b)
Solutions
- Use a chain/RPC that supports EIP-1559 (London hardfork activated) so headers include base_fee_per_gas.
- Check the verification provider configuration so full modern headers are returned, not legacy/stripped ones.
- Ensure the decision block is a recent block, not genesis or a pre-London historical block.
- Update the node/client software if it predates EIP-1559 header support.
Defensive patterns
Strategy: validation
Validate before calling
pub fn header_is_eip1559(h: &VerifiedBlockHeader) -> bool {
h.base_fee_per_gas.is_some()
} Type guard
fn has_base_fee(h: &VerifiedBlockHeader) -> Option<u64> { h.base_fee_per_gas } Try / catch
match result {
Err(e) if e.to_string().contains("has no base fee") => return Err(config_error("chain must have EIP-1559 activated")),
other => other,
} Prevention
- Deploy only on EIP-1559-capable chains (London+).
- Validate in startup config that the target chain post-dates London.
- Use a verification provider that returns full modern headers.
When it happens
Trigger: `prepare_and_sign_with_anchors` obtains a decision header whose `base_fee_per_gas` field is None — e.g. verifying a pre-London (pre-EIP-1559) block, a header source that omits the field, or a genesis/legacy header used as the decision block.
Common situations: Pointing the client at a chain that never activated EIP-1559 (or an old archive snapshot); a verification provider returning stripped/partial headers; misconfigured node or RPC that serves legacy block format.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Missing fee in topic3 when parsing pool created event
- Initialize event missing topics: expected 4, was {topics_len
- Initialize event missing topics: expected 4, was {log_topics
- Persisted signed transaction is not EIP-1559
- Pool state at block {} has no ingestion-time block hash; ref
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bc71925ade27438a.
Report an issue: GitHub.