jdx/mise · error

forced publication is not supported

Error message

forced publication is not supported

What it means

push refuses refspecs that begin with '+' (force-push). Force publication would overwrite history on the origin branch, which this history-sync code forbids by design; when the remote branch moved, the caller is told to fetch and reconcile instead.

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 afd2eddd3a)

Solutions

  1. Remove the leading '+' from the refspec and push normally.
  2. When push is rejected because the origin branch changed, fetch and reconcile (rebase/merge) locally, then push again.
  3. If history truly must be rewritten on origin, do it outside this API with plain git push --force, acknowledging the history-sync store does not support it.

Example fix

// before
let outcome = remote.push(&["+main:main"])?;
// after
let outcome = remote.push(&["main:main"])?; // fetch + reconcile if rejected
Defensive patterns

Strategy: validation

Validate before calling

let force = refspecs.iter().any(|r| r.starts_with('+'));
if force { eprintln!("drop the leading '+' — forced publication is not supported"); }

Try / catch

match remote.push(&refspecs) {
    Err(e) if e.to_string().contains("forced publication") => {
        // rebuild refspecs without '+' and reconcile first
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling push with any refspec string starting with '+', e.g. '+main:main' or '+refs/heads/*:refs/heads/*', on the history sync network transport.

Common situations: A developer habitually adds '+' to 'make sure' the push lands; a rebased/rewritten local history makes plain push fail and the user reaches for force-push; automation templates carry force refspecs.

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@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/368b9013a4061fcf. Report an issue: GitHub.