linera-io/linera-protocol · error

Failed to clone storage

Error message

Failed to clone storage

What it means

ExportersTracker::spawn (linera-exporter/src/runloops/task_manager.rs:132) clones the shared exporter storage before spawning a per-destination exporter and expects success. ExporterStorage::clone (linera-exporter/src/storage.rs:211) is a fallible custom clone: it re-clones the underlying linera storage backend, which can return Err (e.g. storage client/pool construction failing against a misconfigured or unreachable database). The panic aborts the runloop thread that manages exporters.

Source

Thrown at linera-exporter/src/runloops/task_manager.rs:138

        }
    }

    pub(super) async fn join_all(self) {
        for (id, handle) in self.join_handles {
            // Wait for all tasks to finish.
            if let Err(e) = handle.await.unwrap() {
                tracing::error!(id=?id, error=?e, "failed to join task");
            }
        }
    }

    fn spawn(&mut self, id: DestinationId) {
        if self.join_handles.contains_key(&id) {
            tracing::trace!(id=?id, "exporter already running, skipping spawn");
            return;
        }
        let exporter_builder = &self.exporters_builder;
        let storage = self.storage.clone().expect("Failed to clone storage");
        let join_handle = exporter_builder.spawn(id.clone(), storage);
        self.join_handles.insert(id, join_handle);
    }
}

/// All the data required by a thread to spawn different tasks
/// on its runtime, join the thread, handle the committees etc.
pub(super) struct ExporterBuilder<F> {
    options: NodeOptions,
    work_queue_size: usize,
    node_provider: Arc<GrpcNodeProvider>,
    shutdown_signal: F,
    health: Arc<AtomicBool>,
}

impl<F> ExporterBuilder<F>
where
    F: IntoFuture<Output = ()> + Clone + Send + Sync + 'static,

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Verify the storage backend is reachable with the connection settings in the exporter config (e.g. psql for Postgres endpoints).
  2. Correct the storage connection string / credentials in the config and restart the exporter.
  3. Check exporter logs just before the panic for the underlying storage error naming the real cause.
  4. If the DB restarts, restart the exporter so storage clones succeed on the next spawn.
Defensive patterns

Strategy: validation

Validate before calling

// Validate storage connectivity before launching the exporter runloop:
// (example for a Postgres-backed storage)
let conn = tokio_postgres::connect(&config.storage.connection_string, tokio_postgres::NoTls).await;
if conn.is_err() {
    anyhow::bail!("storage backend unreachable; fix the connection string before starting exporters");
}

Prevention

When it happens

Trigger: A committee change or startup causing spawn() for a new DestinationId while the underlying storage backend's clone fails - typically a bad connection string or a database (Postgres/DynamoDB/ScyllaDB) that is unreachable or rejecting connections at clone time.

Common situations: Exporter config's storage connection string wrong or pointing at a down database; DB credentials rotated after exporter start; network partition to the storage endpoint while committees rotate, triggering a spawn attempt.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/ecd0e57bdd4e35b4. Report an issue: GitHub.