gitbutlerapp/gitbutler · error

push failed

Error message

push failed

What it means

After publishing session metadata, but-agentlog pushes the GitMeta ref in a retry loop (up to 5 attempts) that only retries non-fast-forward conflicts. This bail means `push_once` reported failure with `non_fast_forward == false` — the push was rejected for a reason other than a racing writer, so retrying the loop would not help. Typical causes are authentication, network, or remote-ref problems on the metadata remote.

Source

Thrown at crates/but-agentlog/src/gitmeta/write.rs:298

    match gitmeta.pull(None) {
        Ok(_) => {}
        // An empty metadata remote has no ref yet; the push below initializes it.
        Err(git_meta_lib::Error::GitCommand(message))
            if message.contains("couldn't find remote ref") => {}
        Err(err) => return Err(err).context("failed to pull GitMeta metadata"),
    }

    let mut attempts = 0;
    loop {
        attempts += 1;
        let output = gitmeta
            .push_once(None)
            .context("failed to push GitMeta metadata")?;
        if output.success {
            return Ok(());
        }
        if !output.non_fast_forward {
            bail!("push failed");
        }
        if attempts >= MAX_RETRIES {
            bail!("push failed after {MAX_RETRIES} attempts");
        }
        gitmeta
            .resolve_push_conflict(None)
            .context("failed to resolve GitMeta push conflict")?;
    }
}

fn stored_text(kind: RecordKind, text: Option<&str>) -> Option<String> {
    let text = text?;
    Some(match kind {
        RecordKind::ToolResult => redact_text(cap_tool_result_text(text).as_ref()),
        _ => redact_text(text),
    })
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Check network access and credentials for the GitMeta remote (`git ls-remote <metadata-remote-url>`) and fix auth
  2. Run `but agentlog sync` to confirm pull works, then retry publish — local state is intact, only the push failed
  3. Verify the GitMeta remote repository still exists and the account has push rights
  4. Re-run publish once auth is fixed; the record dedup (`:record-hashes`) prevents duplicates on the retry

Example fix

// before: single publish call surfaces the raw bail
publish_session(&repo, &session)?;

// after: retry publish after fixing auth, dedup makes it idempotent
let mut last_err = None;
for _ in 0..3 {
    match publish_session(&repo, &session) {
        Ok(()) => { last_err = None; break }
        Err(e) if e.to_string().contains("push failed") => { last_err = Some(e); continue }
        Err(e) => return Err(e),
    }
}
if let Some(e) = last_err { return Err(e.context("metadata push rejected; check GitMeta remote auth")) }
Defensive patterns

Strategy: retry

Validate before calling

// Verify the metadata remote is reachable and writable before publish
let ok = std::process::Command::new("git")
    .args(["ls-remote", &metadata_remote_url])
    .output()
    .map(|o| o.status.success())
    .unwrap_or(false);
if !ok { eprintln!("GitMeta remote unreachable or unauthorized"); }

Type guard

fn push_output_is_retryable(output: &PushOutput) -> bool {
    !output.success && output.non_fast_forward
}

Try / catch

match publish(&repo, &session) {
    Ok(()) => {}
    Err(err) if err.to_string().contains("push failed") => {
        // fix auth/network, then retry: record dedup makes this idempotent
        retry_after_auth_fix()
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: The final step of `but agentlog publish` (or sync) calling `gitmeta.push_once` and getting an unsuccessful output that is not a non-fast-forward rejection — e.g. expired credentials for the GitMeta remote, unreachable remote, or permission loss on the remote ref.

Common situations: Expired SSH key or credential helper for the metadata remote URL; VPN/network drop mid-publish; the GitMeta remote repository was deleted or made read-only; remote hosting auth changes (token revoked, SSO enforced).

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/82353dda6ba5d678. Report an issue: GitHub.