dani-garcia/vaultwarden · critical

Failed to load

Error message

Failed to load {key}: {e:?}

What it means

When a config key is supplied only via KEY_FILE, Vaultwarden reads the file with fs::read_to_string at startup. This panic fires if that file cannot be read (missing, unreadable, or invalid path), aborting configuration loading.

Solutions

  1. Verify the file exists and is readable by the Vaultwarden process user (ls -l, stat)
  2. Check container volume/secrets mounts (docker inspect, kubectl get pod -o yaml)
  3. Fix the X_FILE path in your env configuration; use an absolute path
  4. Test with: cat $X_FILE inside the container to reproduce the exact OS error shown in the panic

Example fix

// before
docker-compose: ADMIN_TOKEN_FILE: ./secrets/admin_token.txt  (not copied into image)
// after
volumes:
  - ./secrets/admin_token.txt:/run/secrets/admin_token:ro
environment:
  ADMIN_TOKEN_FILE: /run/secrets/admin_token
Defensive patterns

Strategy: validation

Validate before calling

const path = process.env.ADMIN_TOKEN_FILE;
if (path) {
  const fs = require('fs');
  if (!fs.existsSync(path) || !fs.statSync(path).isFile()) throw new Error(`${path} missing or not a file`);
  fs.accessSync(path, fs.constants.R_OK);
}

Type guard

function readableFile(p) { try { return typeof p === 'string' && require('fs').statSync(p).isFile() && require('fs').accessSync(p, require('fs').constants.R_OK) === undefined; } catch { return false; } }

Prevention

When it happens

Trigger: X_FILE points to a non-existent file, the process lacks read permission, the path is a directory, or the secret mount failed (empty/failed volume mount in Docker/Kubernetes).

Common situations: Kubernetes secret not mounted before startup; Docker secrets typo in the mount path; SELinux/AppArmor blocking access; file deleted by tmpfs cleanup; path containing trailing whitespace or unexpanded $VARS.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of dani-garcia/vaultwarden@cc67d644f6 (2026-09-19). Data as JSON: /api/errors/d7cb87b561e80b10. Report an issue: GitHub.

Appendix: source

Thrown at src/util.rs:444

    } else {
        None
    }
}

//
// Env methods
//
pub fn get_env_str_value(key: &str) -> Option<String> {
    let key_file = format!("{key}_FILE");
    let value_from_env = env::var(key);
    let value_file = env::var(&key_file);

    match (value_from_env, value_file) {
        (Ok(_), Ok(_)) => panic!("You should not define both {key} and {key_file}!"),
        (Ok(v_env), Err(_)) => Some(v_env),
        (Err(_), Ok(v_file)) => match std::fs::read_to_string(v_file) {
            Ok(content) => Some(content.trim().to_owned()),
            Err(e) => panic!("Failed to load {key}: {e:?}"),
        },
        _ => None,
    }
}

pub fn get_env<V>(key: &str) -> Option<V>
where
    V: FromStr,
{
    try_parse_string(get_env_str_value(key))
}

pub fn get_env_bool(key: &str) -> Option<bool> {
    const TRUE_VALUES: &[&str] = &["true", "t", "yes", "y", "1"];
    const FALSE_VALUES: &[&str] = &["false", "f", "no", "n", "0"];

    match get_env_str_value(key) {
        Some(val) if TRUE_VALUES.contains(&val.to_lowercase().as_ref()) => Some(true),

View on GitHub (pinned to cc67d644f6)