linera-io/linera-protocol · critical
invalid block export configuration: {message}
Error message
invalid block export configuration: {message} What it means
spawn_block_export_queue is the single entry point for the block-export pipeline and runs BlockExportConfig::check() first, panicking with the failed rule's message if the config is invalid. This is a deliberate fail-fast: every constructor (CLI, tests, programmatic) must pass a sane config, and misconfiguration aborts at startup rather than corrupting an export mid-run.
Source
Thrown at linera-core/src/chain_worker/export.rs:535
/// Spawns the process-wide export queue task and returns the handle chain workers push to.
///
/// The task runs until every clone of the returned handle is dropped, and reads only from
/// `storage` — never through a chain worker, whose TTL a touch would reset.
pub fn spawn_block_export_queue<S, P>(
storage: S,
node_provider: Arc<P>,
config: BlockExportConfig,
own_public_key: Option<ValidatorPublicKey>,
) -> BlockExportHandle
where
S: Storage + Clone + Send + Sync + 'static,
P: ValidatorNodeProvider + Send + Sync + 'static,
P::Node: Send + Sync,
{
// Enforced here rather than only at the CLI: every constructor, tests included, must go
// through it, and an invalid config panics at startup instead of mid-export.
if let Err(message) = config.check() {
panic!("invalid block export configuration: {message}");
}
let (blocks, receiver) = mpsc::channel(config.queue_size);
let progress: SharedProgress = Arc::default();
let tips: SharedTips = Arc::default();
let queued_bytes = Arc::new(std::sync::atomic::AtomicUsize::new(0));
let queue_bytes_budget = config.queue_bytes;
let max_in_flight_total = config.max_in_flight_total;
let task = BlockExportQueue {
storage,
node_provider,
config,
own_public_key,
latest_epoch: None,
committee: None,
committee_dirty: false,
admin_chain_id: None,
ticks_until_scan: 0,View on GitHub (pinned to 6c226ddcb3)
Solutions
- Read the panic message — it names the exact field and rule (e.g. 'block export queue size must be greater than zero'); fix that field.
- Prefer deriving from the defaults (queue_size 1024, queue_bytes 256 MiB, …) and overriding individual fields instead of constructing from scratch.
- If constructing configs programmatically, run config.check()? yourself first and surface the error instead of panicking.
Example fix
// before
let config = BlockExportConfig { queue_size: 0, ..Default::default() };
spawn_block_export_queue(config, ...); // panics
// after
let config = BlockExportConfig { ..Default::default() }; // queue_size = 1024
config.check()?; // surface a Result, don't panic
spawn_block_export_queue(config, ...); Defensive patterns
Strategy: validation
Validate before calling
// Rust
let mut config = BlockExportConfig::default(); // sane baseline (queue_size 1024, queue_bytes 256 MiB, ...)
// apply overrides, then:
if let Err(msg) = config.check() {
return Err(format!("invalid block export configuration: {msg}"));
}
spawn_block_export_queue(config, ...); Type guard
fn valid_export_config(config: &BlockExportConfig) -> bool { config.check().is_ok() } Prevention
- Never construct BlockExportConfig from scratch with ..Default::default() blind spots; start from default() and override explicitly.
- Run config.check() in config-loading code (CLI, tests) and surface the message instead of letting the spawn panic.
- Watch for deserialized configs with missing fields defaulting to 0 — the zero values are exactly what check() rejects.
When it happens
Trigger: Any BlockExportConfig with a zero limit or inverted bounds reaches spawn: certificate_upload_batch_size == 0, queue_size == 0, queue_bytes == 0, max_in_flight_per_destination == 0, max_in_flight_total == 0, max_in_flight_total < max_in_flight_per_destination, max_catch_up_blocks == 0, or a zero idle_catch_up_interval. Typical sources: a config file missing fields that deserialize to 0, manual construction in tests, or CLI overrides zeroing a value.
Common situations: Hand-rolled configs in tests that only set a few fields; config files from an older/newer version missing newer knobs (defaulting to 0); scripts copying a partial config template; 'disable this feature by setting it to 0' assumptions colliding with the validator.
Related errors
- owner should be different from spender
- Returned AccountInfo should have code: Some(...) and so code
- Returned AccountInfo should have code: Some(...) and so code
- unexpected query response: {other:?}
- Cannot apply default storage because the feature 'rocksdb' w
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/b7e197f8e9da5e86.
Report an issue: GitHub.