jdx/mise · error

cannot synchronize

Error message

cannot synchronize: {reason}

What it means

After enabling-history and opening the store, sync checks `store.unavailable()` and aborts with 'cannot synchronize: {reason}' if the history store cannot be used. The store's own reason is included so the user knows what to fix.

Solutions

  1. Read the embedded reason in the error message
  2. Verify/create the history state directory and fix permissions
  3. Re-initialize or repair the store if it is corrupt, then retry `mise dot sync`

Example fix

// before
mise dot sync  // cannot synchronize: store version mismatch
// after
mise dot status          # inspect store state
mise dot track ...       # re-baseline if store was reset
mise dot sync
Defensive patterns

Strategy: try-catch

Validate before calling

store_dir=~/.local/share/mise/dotfiles-history
[ -d "$store_dir" ] && [ -r "$store_dir" ] && [ -w "$store_dir" ] || echo "store dir missing or permission problem"
mise dot status > /dev/null || echo "store fails to open: repair before syncing"

Try / catch

mise dot sync || {
  reason=$(mise dot status 2>&1)
  echo "sync aborted; store state: $reason"
  exit 1
}

Prevention

When it happens

Trigger: Running `mise dot sync` when Store::unavailable() returns Some(reason) — e.g. the store directory is missing, corrupt, version-incompatible, or not writable.

Common situations: Fresh machine before any history store was created; corrupted store from a crash; permission problems on the state directory; store written by an incompatible mise version.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at src/cli/dotfiles/sync.rs:49

impl DotfilesSync {
    pub(crate) async fn run(self) -> Result<()> {
        match self.sync().await {
            Ok(()) => Ok(()),
            Err(err) if self.best_effort && is_network_failure(&err) => {
                warn!("history sync: {err:#}");
                Ok(())
            }
            Err(err) => Err(err),
        }
    }

    async fn sync(&self) -> Result<()> {
        if !crate::config::Settings::get().history.enabled {
            bail!("history is disabled (history.enabled = false)");
        }
        let (store, tracked, _) = super::history::open().await?;
        if let Some(reason) = store.unavailable() {
            bail!("cannot synchronize: {reason}");
        }
        let mut request = SyncRequest::new(self.fetch_only);
        request.allow_plaintext_history = self.allow_plaintext_history;
        let outcome = run::sync(&store, &tracked, &request)?;
        crate::system::history::sync::origin::report(&outcome);
        Ok(())
    }
}

fn is_network_failure(error: &eyre::Report) -> bool {
    error
        .downcast_ref::<crate::system::history::sync::network::NetworkError>()
        .is_some()
}

#[cfg(test)]
mod tests {
    use super::*;

View on GitHub (pinned to 533346cc37)