jdx/mise · error

invalid manifest {manifest:?} for dotfile {target}

Error message

invalid manifest {manifest:?} for dotfile {target}

What it means

The `manifest` key is only valid for `mode = "copy"` or `mode = "symlink-each"` entries, and its value must parse as a valid file manifest (via `FileManifest::parse`). A manifest on any other mode, or a string that is not a recognized manifest, makes the entry invalid and aborts validation.

Source

Thrown at src/system/files.rs:624

                        || content.is_some()
                        || manifest.is_some()
                        || exclude.is_some())
                {
                    bail!(
                        "tracked file {target} cannot declare source, content, manifest, or exclude"
                    );
                }
                if source.is_some() && content.is_some() {
                    bail!("dotfile {target} cannot declare both source and content");
                }
                if mode != FileMode::Track && source.is_none() && content.is_none() {
                    implied_source(&resolve_target_arg(&target))?;
                }
                if let Some(manifest) = manifest
                    && (FileManifest::parse(&manifest).is_none()
                        || !matches!(mode, FileMode::Copy | FileMode::SymlinkEach))
                {
                    bail!("invalid manifest {manifest:?} for dotfile {target}");
                }
                for pattern in exclude.into_iter().flatten() {
                    glob::Pattern::new(&pattern)?;
                }
            }
        }
    }
    Ok(())
}

/// Aggregate `[dotfiles]` across a specific set of config files. This is
/// used by OCI builds, which intentionally scope config to project files by
/// default instead of blindly inheriting global dotfiles.
pub(crate) fn files_from_config_files(config_files: &ConfigMap) -> Vec<FileRequest> {
    files_from_config_files_with_tracking_roots(config_files, None)
}

fn files_from_config_files_with_tracking_roots(

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Change the entry's mode to `copy` or `symlink-each` if a manifest is required.
  2. Otherwise remove the `manifest` key from entries that don't use copy/symlink-each.
  3. Verify the manifest string matches the expected format accepted by `FileManifest::parse`.

Example fix

// before
[dotfiles."~/.config/app"]
source = "app"
manifest = "links.toml"

// after
[dotfiles."~/.config/app"]
source = "app"
mode = "symlink-each"
manifest = "links.toml"
Defensive patterns

Strategy: validation

Validate before calling

const MANIFEST_MODES = new Set(['copy', 'symlink-each']);
function assertManifestEntry(entry, target) {
  if (entry.manifest != null && !MANIFEST_MODES.has(entry.mode))
    throw new Error(`${target}: manifest requires copy or symlink-each mode`);
}

Try / catch

try {
  applyDotfiles();
} catch (e) {
  if (/invalid manifest/.test(e.message)) {
    console.error('Set mode to copy/symlink-each, or remove the manifest key, and verify its format');
  } else throw e;
}

Prevention

When it happens

Trigger: Setting `manifest = "..."` on an entry whose resolved mode is the default (symlink), track, or template; or supplying a malformed manifest string that `FileManifest::parse` cannot interpret.

Common situations: Adding `manifest` to a symlinked dotfile expecting per-link control, misspelling the manifest format, or copying a manifest snippet between entries with different modes.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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