atuinsh/atuin · error

No encryption key provided

Error message

No encryption key provided

What it means

During login, `prompt_and_store_key` must obtain the encryption key: either from the `--key` flag or interactively. If stdin is exhausted (EOF) the read returns None and re-prompting would loop forever, so it bails with 'No encryption key provided'.

Solutions

  1. Pass the key explicitly: `atuin login --key <your key>`
  2. Pipe the key into stdin: `echo "$ATUIN_KEY" | atuin login ...` so the read succeeds
  3. Run login once in an interactive terminal to store the key, then automate the rest

Example fix

// before
echo "$PW" | atuin login -u me   # stdin EOFs before key prompt
// after
echo "$ATUIN_KEY" | atuin login -u me --key "$ATUIN_KEY"
# or simply: atuin login -u me --key "$ATUIN_KEY"
Defensive patterns

Strategy: validation

Validate before calling

[ -n "$ATUIN_KEY" ] || { echo 'ATUIN_KEY required for non-interactive login'; exit 1; }
atuin login -u "$USER" --key "$ATUIN_KEY"

Try / catch

atuin login --key "$ATUIN_KEY" || { echo 'login failed; check key'; exit 1; }

Prevention

When it happens

Trigger: Running `atuin login` non-interactively (no TTY, stdin closed or redirected from /dev/null) without `--key`; automation scripts that never supply the key.

Common situations: CI/containers running `atuin login` with piped credentials but no key; scripts that redirect stdin; tmux/ssh sessions with detached stdin.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at crates/atuin/src/command/client/account/login.rs:210

        println!("IMPORTANT");
        println!(
            "If you are already logged in on another machine, you must ensure that the key you \
             use here is the same as the key you used there."
        );
        println!("You can find your key by running 'atuin key' on the other machine.");
        println!("Do not share this key with anyone.");
        println!("\nRead more here: {} \n", atuin_common::docs::url("guide/sync/#login"));

        let interactive = self.interactive();
        let mut flag_key = self.key.clone();

        loop {
            let key = match flag_key.take() {
                Some(key) => key,
                None => match read_user_input("encryption key [blank to use existing key file]") {
                    Some(key) => key,
                    // Stdin is exhausted, so re-prompting would spin forever.
                    None => bail!("No encryption key provided"),
                },
            };

            if key.is_empty() {
                if !key_path.exists() {
                    let msg = "No key provided and no existing key file found. Please use 'atuin \
                               key' on your other machine, or recover your key from a backup";
                    if !interactive {
                        bail!(msg);
                    }
                    println!("\n{msg}\n");
                    continue;
                }

                paseto_v4::Key::try_load_from_path(key_path).context(format!(
                    "The key in existing key file at '{}' is invalid",
                    key_path.to_string_lossy()
                ))?;

View on GitHub (pinned to 900007c480)