jdx/mise · error

conflicting managed directory declarations for {} first:

Error message

conflicting managed directory declarations for {}

  first:
    {}

  second:
    {}

What it means

Thrown by directories_from_config when two configuration layers declare the same managed directory path with differing declarations (e.g. different state: present vs absent, or different mode). Because directory declarations must be consistent across layers, the mismatch is reported with both conflict descriptions.

Source

Thrown at src/system/managed_files.rs:430

                merged
                    .entry(target)
                    .or_insert_with(|| (file, base.clone(), file_origin));
            }
        }
    }
    Ok(merged)
}

fn directories_from_config(config: &Config) -> Result<Vec<ManagedDirectoryRequest>> {
    let mut composed: IndexMap<PathBuf, (ManagedDirectoryTomlConfig, ResourceOrigin)> =
        IndexMap::new();
    for config_files in config.bootstrap_config_maps() {
        for (path, declaration) in directories_from_config_files(config_files)? {
            if let Some(existing) = composed.get(&path) {
                if existing.0 == declaration.0 {
                    continue;
                }
                bail!(
                    "conflicting managed directory declarations for {}\n\n  first:\n    {}\n\n  second:\n    {}",
                    path.display(),
                    existing.1.conflict_description(),
                    declaration.1.conflict_description(),
                );
            }
            composed.insert(path, declaration);
        }
    }
    composed
        .into_iter()
        .map(|(path, (config, origin))| ManagedDirectoryRequest::from_toml(path, config, origin))
        .collect()
}

/// Merges managed directories within one config hierarchy using normal precedence.
fn directories_from_config_files(
    config_files: &ConfigMap,

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Read the 'first:'/'second:' conflict descriptions to find the differing field (state or mode).
  2. Remove the directory declaration for that path from one config layer.
  3. Align both layers to the same state and mode if both must exist.
  4. If a directory is intentionally removed in an environment override, ensure no other active layer still declares it present.

Example fix

# before
# user config: state = "absent"  project config: state = "present" for /var/log/myapp
# after
# remove the user-config declaration, or set both to state = "present"
Defensive patterns

Strategy: validation

Validate before calling

const merged = {};
for (const layer of layers) {
  for (const [path, decl] of Object.entries(layer.directories)) {
    if (merged[path] && (merged[path].state !== decl.state || merged[path].mode !== decl.mode)) {
      throw new Error(`conflicting managed directory declarations for ${path}`);
    }
    merged[path] = decl;
  }
}

Prevention

When it happens

Trigger: Calling status_requests_from_config or prepare_requests_from_config when bootstrap_config_maps() includes multiple layers that each declare bootstrap.directories for path P with non-equal declarations.

Common situations: One config layer marks a directory as absent (cleanup) while another marks it present; different permissions/mode per layer; stale project-level overrides after a team changed the shared config.

Related errors


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