jdx/mise · error

{} changed while preparing enrollment; concurrent declaratio

Error message

{} changed while preparing enrollment; concurrent declaration edit preserved; retry

What it means

While enrolling a dotfile, mise verifies the declaration file's contents still match what was read earlier (`expected`). If the on-disk content changed between read and commit — a concurrent edit — track aborts instead of overwriting someone else's change, telling the user to retry.

Source

Thrown at src/cli/dotfiles/track.rs:316

    declaration_lock_for(&crate::config::global_shared_config_path())
}

fn declaration_lock_for(config: &Path) -> Result<fslock::LockFile> {
    crate::lock_file::LockFile::new(&config.with_extension("dotfiles-declarations.lock"))
        .try_lock()?
        .ok_or_else(|| {
            eyre::eyre!("another tracking declaration command is running; retry shortly")
        })
}

fn check_declaration(path: &Path, expected: Option<&str>) -> Result<()> {
    let current = match std::fs::read_to_string(path) {
        Ok(body) => Some(body),
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => None,
        Err(error) => return Err(error.into()),
    };
    if current.as_deref() != expected {
        bail!(
            "{} changed while preparing enrollment; concurrent declaration edit preserved; retry",
            display_path(path)
        );
    }
    Ok(())
}

fn commit_declaration(
    path: &Path,
    expected: Option<&str>,
    prepared: file::PreparedAtomicWrite,
) -> Result<()> {
    // Check after formatting, directory creation, writing, and fsync. The
    // declaration lock coordinates mise writers; unrelated editors do not
    // participate, so this is not a filesystem compare-and-swap guarantee.
    check_declaration(path, expected)?;
    prepared.commit()
}

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Retry `mise bootstrap dotfiles track <target>` once the other edit settles
  2. Ensure no editor or process is writing the declaration file concurrently
  3. Commit declaration edits through one tool at a time
Defensive patterns

Strategy: retry

Validate before calling

# ensure no writer holds the declaration file before tracking
flock -n /path/to/declarations.lock -c 'mise bootstrap dotfiles track ~/target' || echo 'declaration busy'

Try / catch

until mise bootstrap dotfiles track ~/target 2>&1; do
  case "$?" in 0) break;; esac
  grep -q 'concurrent declaration edit' log && sleep 1 || break
done

Prevention

When it happens

Trigger: `dotfiles track` preparing enrollment of a declaration (e.g. declarations file in mise config) while another process/editor modifies that file between the initial read and the `check_declaration` compare-then-commit.

Common situations: Two terminals running `dotfiles track`/config edits simultaneously; an editor auto-saving the declaration file mid-command; sync tools (dropbox/git hooks) touching the file during enrollment.

Related errors


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