jdx/mise · error

encrypted dotfile {target} requires an external source, not

Error message

encrypted dotfile {target} requires an external source, not inline content or edits

What it means

An encrypted dotfile's plaintext is fetched from an external source (mise decrypts it before applying), so it cannot also declare inline `content`, edits (`block`, `line`), or a `template` — there is no way to combine encryption with inline body definitions. validate_incoming_files rejects any entry with encrypt = true that contains any of those keys.

Source

Thrown at src/system/files.rs:543

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))
                }) {
                    continue;
                }
                bail!("invalid dotfile declaration {target} in {}", path.display());
            };
            if let Some(table) = value.as_table() {
                for key in table.keys() {
                    if !matches!(

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Move the file's body into an external file, encrypt it (e.g. with age/sops/gpg), and reference it via source; keep encrypt = true.
  2. Remove encrypt = true if the content truly is inline (and encrypt the file some other way).
  3. Remove the content/block/line/template keys — encrypted entries must not carry inline bodies or managed edits; manage edits in the decrypted source workflow instead.

Example fix

# before
[dotfiles."~/.aws/credentials"]
encrypt = true
content = "[default]\naws_access_key_id=..."

# after
[dotfiles."~/.aws/credentials"]
encrypt = true
source = "~/secrets/aws-credentials.age"
Defensive patterns

Strategy: validation

Validate before calling

# reject encrypted entries carrying inline bodies
awk '/encrypt = true/{e=1} e && /^(content|block|line|template) *=/{print "conflict"; exit}' mise.toml

Type guard

const encryptedEntryIsValid = (t: Record<string, unknown>) =>
  t.encrypt !== true || !["content","block","line","template"].some(k => k in t);

Prevention

When it happens

Trigger: A [dotfiles."<target>"] entry with encrypt = true that also declares one of content, block, line, or template; the validator's key scan matches and it bails immediately.

Common situations: The user wants to encrypt a file but wrote the body inline in mise.toml (content = "...") or layered managed edits on an encrypted file; converting a previously inline dotfile to encrypt = true without moving the content to an external encrypted file.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/9af9cdf192a81362. Report an issue: GitHub.