atuinsh/atuin · error

trailing bytes in encoded shell alias record. malformed

Error message

trailing bytes in encoded shell alias record. malformed

What it means

The alias record deserializer in atuin-dotfiles/src/store.rs decodes a Create alias record as two length-prefixed strings (key, value). If bytes remain in the buffer after reading both strings, the payload framing is invalid, so it bails with "trailing bytes in encoded shell alias record. malformed" — a corruption/protocol guard on the binary record format.

Solutions

  1. Locate and delete the malformed alias record from the record store so a clean copy can re-sync
  2. Upgrade atuin on all devices to matching versions to remove format skew
  3. Back up and check the records database for corruption
  4. As a last resort, reset the dotfiles/record store and re-sync
Defensive patterns

Strategy: try-catch

Try / catch

match alias_decode_result {
    Err(e) if e.to_string().contains("trailing bytes in encoded shell alias record") => {
        // drop/quarantine the malformed record and re-sync
    }
    other => other?,
}

Prevention

When it happens

Trigger: Deserializing a shell-alias record (type Create) whose encoded payload carries extra bytes after name+value — caused by a record written by a different record-format version or a corrupted/truncated record received during sync.

Common situations: Record store data produced by an incompatible atuin version; partial writes or corruption in the local records DB; malicious/malformed records from a compromised sync peer.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19). Data as JSON: /api/errors/598817b97083a146. Report an issue: GitHub.

Appendix: source

Thrown at crates/atuin-dotfiles/src/store.rs:80

                let mut bytes = decode::Bytes::new(&data.0);

                let record_type = decode::read_u8(&mut bytes).map_err(error_report)?;

                match record_type {
                    // create
                    0 => {
                        let nfields = decode::read_array_len(&mut bytes).map_err(error_report)?;
                        ensure!(nfields == 2, "too many entries in v0 shell alias create record");

                        let bytes = bytes.remaining_slice();

                        let (key, bytes) =
                            decode::read_str_from_slice(bytes).map_err(error_report)?;
                        let (value, bytes) =
                            decode::read_str_from_slice(bytes).map_err(error_report)?;

                        if !bytes.is_empty() {
                            bail!("trailing bytes in encoded shell alias record. malformed");
                        }

                        Ok(Self::Create(Alias {
                            name: key.to_owned(),
                            value: value.to_owned(),
                        }))
                    }

                    // delete
                    1 => {
                        let nfields = decode::read_array_len(&mut bytes).map_err(error_report)?;
                        ensure!(nfields == 1, "too many entries in v0 shell alias delete record");

                        let bytes = bytes.remaining_slice();

                        let (key, bytes) =
                            decode::read_str_from_slice(bytes).map_err(error_report)?;

View on GitHub (pinned to 900007c480)