atuinsh/atuin · error

stored value is a valid CommandCapture

Error message

stored value is a valid CommandCapture

What it means

`get()` in the fjall output-capture backend reads a stored value and calls `ActiveSchema::deserialize_value`, expecting all stored values to be valid `CommandCapture` blobs written by the same schema. Panicking means a value in the keyspace cannot be deserialized — corrupted data or a schema/version mismatch between writer and reader.

Source

Thrown at crates/atuin-daemon/src/output_capture/backend/fjall/mod.rs:91

                    Ok(())
                }
                // Another writer committed this key first, so it's already captured.
                Err(fjall::Conflict) => Err(CaptureError::AlreadyExists),
            }
        })
        .await
        .expect("output-capture write task panicked")
    }

    async fn get(&self, id: HistoryId) -> Result<Option<CommandCapture>, GetOutputError> {
        let keyspace = self.keyspace.clone();
        let key = ActiveSchema::serialize_key(id).expect("history id serialization is infallible");

        tokio::task::spawn_blocking(move || {
            match keyspace.get(key).map_err(|err| GetOutputError::Storage(Box::new(err)))? {
                Some(slice) => {
                    let capture = ActiveSchema::deserialize_value(slice.to_vec())
                        .expect("stored value is a valid CommandCapture");
                    Ok(Some(capture))
                }
                None => Ok(None),
            }
        })
        .await
        .expect("output-capture read task panicked")
    }

    async fn remove(&self, ids: Vec<HistoryId>) -> Result<(), DeleteOutputError> {
        let keys: Vec<_> = ids
            .into_iter()
            .map(|id| {
                ActiveSchema::serialize_key(id).expect("history id serialization is infallible")
            })
            .collect();
        if keys.is_empty() {
            return Ok(());

View on GitHub (pinned to c0c717ab04)

Solutions

  1. Ensure the Atuin version reading the data is not older than the version that wrote it
  2. If corruption is suspected, delete/rebuild the output-capture keyspace from history
  3. Restore from a consistent backup that includes matching schema versions
  4. Report a bug if it reproduces on a single unmodified installation

Example fix

// before
.expect("stored value is a valid CommandCapture");
// after
ActiveSchema::deserialize_value(slice.to_vec())
    .map_err(|err| GetOutputError::Schema(Box::new(err)))?
Defensive patterns

Strategy: fallback

Try / catch

// Treat undecodable values as missing instead of panicking:
let capture = match ActiveSchema::deserialize_value(slice.to_vec()) {
    Ok(c) => c,
    Err(e) => { tracing::warn!("undecodable capture: {e}"); return Ok(None); }
};

Prevention

When it happens

Trigger: Calling `get(id)` for a history id whose stored bytes were written by a different Atuin/fjall schema version, were corrupted on disk, or were truncated by an unclean shutdown.

Common situations: Downgrading Atuin after a schema change; restoring a partial/inconsistent data directory from backup; disk corruption; manually copying keyspace files between machines with different versions.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12). Data as JSON: /api/errors/3bf7de5c0adb3e77. Report an issue: GitHub.