jdx/mise · error

dotfile : encrypt must be a boolean

Error message

dotfile {target}: encrypt must be a boolean

What it means

`validate_incoming_files` checks each `[dotfiles]` entry's table fields before parsing. If an entry contains an `encrypt` key whose value cannot be parsed as a boolean (e.g. a string `"true"`, `"yes"`, or a number), the strict validation bails with this message.

Solutions

  1. Change the value to an unquoted TOML boolean: `encrypt = true` or `encrypt = false`
  2. Remove the `encrypt` key if encryption is not intended

Example fix

// before
"~/.aws/credentials" = { source = "dotfiles/aws", encrypt = "true" }
// after
"~/.aws/credentials" = { source = "dotfiles/aws", encrypt = true }
Defensive patterns

Strategy: validation

Validate before calling

function encryptIsBool(entry) {
  return entry && (entry.encrypt === undefined || typeof entry.encrypt === 'boolean');
}

Type guard

const hasBooleanEncrypt = (e: unknown): e is { encrypt: boolean } => typeof (e as any)?.encrypt === 'boolean';

Prevention

When it happens

Trigger: Writing `encrypt = "true"` or `encrypt = 1` in a dotfile entry table instead of a TOML boolean `encrypt = true`.

Common situations: Users familiar with env-var style configs quote booleans; hand-editing configs and copying the string form from documentation or scripts.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/ef18e9728524f758. Report an issue: GitHub.

Appendix: source

Thrown at src/system/files.rs:639

        && (first.mode != FileMode::Template
            || first.base == second.base
                && config.bootstrap_tera_ctx(&first.origin.config)
                    == config.bootstrap_tera_ctx(&second.origin.config))
}

/// Incoming configuration must fail preflight rather than silently dropping
/// malformed declarations and applying the rest of the setup.
pub(crate) fn validate_incoming_files(config_files: &ConfigMap) -> Result<()> {
    for (path, config) in config_files {
        let Some(dotfiles) = config.dotfiles_config() else {
            continue;
        };
        for (target, value) in dotfiles.0 {
            if value.as_table().is_some_and(|t| {
                t.contains_key("encrypt")
                    && t.get("encrypt").and_then(toml::Value::as_bool).is_none()
            }) {
                bail!("dotfile {target}: encrypt must be a boolean");
            }
            if value.as_table().is_some_and(|t| {
                t.get("encrypt").and_then(toml::Value::as_bool) == Some(true)
                    && ["content", "block", "line", "template"]
                        .iter()
                        .any(|key| t.contains_key(*key))
            }) {
                bail!(
                    "encrypted dotfile {target} requires an external source, not inline content or edits"
                );
            }
            let Some(entry) = file_entry_from_toml(&target, value.clone()) else {
                // Managed line/block edits are handled by the edit engine,
                // not by this whole-file declaration parser.
                if value.as_table().is_some_and(|table| {
                    ["block", "line", "template", "comment", "position"]
                        .iter()
                        .any(|key| table.contains_key(*key))

View on GitHub (pinned to 533346cc37)