jdx/mise · error

forced publication is not supported

Error message

forced publication is not supported

What it means

The push method publishes history refs to the origin setup repository. It deliberately never performs force-pushes: a forced publication would overwrite upstream history that other machines may have based their state on. If any refspec starts with '+', the library bails instead of passing it to git.

Solutions

  1. Fetch from origin and reconcile (merge/rebase) local history with the upstream branch, then push a fast-forward
  2. Remove the '+' prefix from the refspec — use plain "src:dst" refspecs
  3. If upstream was intentionally rewritten, follow the documented reconcile flow (fetch, realign, re-publish) rather than forcing

Example fix

// before
net.push(&repo, &["+refs/history/*:refs/history/*"])?; // bails
// after
net.fetch_with_depth(&repo, "origin", None)?; // reconcile first
net.push(&repo, &["refs/history/*:refs/history/*"])?;
Defensive patterns

Strategy: try-catch

Validate before calling

if refspecs.iter().any(|r| r.starts_with('+')) {
    return Err(anyhow!("remove '+' from refspecs; force-push is not supported"));
}

Try / catch

match net.push(&repo, &refspecs) {
    Ok(PushOutcome::Pushed) => { /* done */ }
    Ok(PushOutcome::Rejected(msg)) | Err(e) => {
        // fetch and reconcile, then retry without forcing
        net.fetch_with_depth(&repo, "origin", None)?;
        reconcile_and_push()?;
    }
}

Prevention

When it happens

Trigger: Calling Network::push with a refspec string beginning with '+' (e.g. "+refs/heads/main:refs/heads/main") — typically constructed by caller code that hit a non-fast-forward and tried to force it through.

Common situations: Diverged local and origin history after another machine rewrote/pushed history; attempting to recover from a rejected push by force; copy-pasted refspecs from generic git workflows that assume --force is fine.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/system/history/sync/network.rs:250

    pub(crate) fn push(
        &self,
        refspecs: &[String],
        lease: Option<(&str, Option<&str>)>,
    ) -> Result<PushOutcome> {
        validate_url(&self.url)?;
        let mut args = vec!["push".to_string(), "--quiet".to_string()];
        if let Some((branch, expected)) = lease {
            let name = format!("refs/heads/{branch}");
            let refs = self.ls_remote()?;
            let observed = refs.iter().find(|(_, candidate)| candidate == &name);
            if observed.map(|(oid, _)| oid.as_str()) != expected {
                return Ok(PushOutcome::Rejected(
                    "the origin branch changed; fetch and reconcile before pushing".into(),
                ));
            }
        }
        if refspecs.iter().any(|refspec| refspec.starts_with('+')) {
            bail!("forced publication is not supported");
        }
        args.push("--".into());
        args.push(self.url.clone());
        args.extend(refspecs.iter().cloned());
        let output = self.repo.network(args.iter().map(String::as_str))?;
        if output.status.success() {
            return Ok(PushOutcome::Done);
        }
        let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
        if stderr.contains("stale info")
            || stderr.contains("rejected")
            || stderr.contains("fetch first")
        {
            return Ok(PushOutcome::Rejected(stderr));
        }
        Err(NetworkError(format!("pushing to {}: {stderr}", self.url)).into())
    }

View on GitHub (pinned to 533346cc37)