gitbutlerapp/gitbutler · error

askpass broker must be initialized

Error message

askpass broker must be initialized

What it means

During a push, git credential prompts are routed to the askpass broker; handle_git_prompt_push expects askpass::get_broker() to return Some. If the broker was never initialized (the application startup step that installs the global broker didn't run), the expect panics with "askpass broker must be initialized".

Solutions

  1. Ensure askpass broker initialization runs before any push (the app's startup/context-setup path that installs the global broker)
  2. Add stored credentials for the remote (git credential store / SSH keys) so no interactive prompt is needed
  3. Downgrade to graceful handling: if get_broker() is None, log and return None instead of panicking

Example fix

// before
askpass::get_broker()
    .expect("askpass broker must be initialized")
    .submit_prompt(prompt, askpass::Context::Push { branch_id })
    .await
// after
match askpass::get_broker() {
    Some(broker) => broker.submit_prompt(prompt, askpass::Context::Push { branch_id }).await,
    None => {
        tracing::warn!("askpass broker not initialized; cannot answer prompt");
        None
    }
}
Defensive patterns

Strategy: fallback

Validate before calling

// Rust: verify the broker is ready before starting a push that may prompt
if askpass::get_broker().is_none() {
    tracing::warn!("askpass broker not initialized; pushes may fail to prompt for credentials");
}

Type guard

fn broker_ready() -> bool {
    askpass::get_broker().is_some()
}

Try / catch

match askpass::get_broker() {
    Some(b) => b.submit_prompt(prompt, askpass::Context::Push { branch_id }).await,
    None => { tracing::warn!("no askpass broker"); None }
}

Prevention

When it happens

Trigger: A push that triggers an authentication prompt (askpass) arrives while the global askpass broker hasn't been set up — i.e. askpass::get_broker() returns None at prompt time.

Common situations: Headless/CLI or test contexts where broker initialization was skipped; initialization order bug where the push starts before the broker is installed; asking for credentials on a private remote without stored credentials, forcing an interactive prompt.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/302bb4e84ca1f1ac. Report an issue: GitHub.

Appendix: source

Thrown at crates/gitbutler-git/src/context.rs:343

        .to_owned();
    Ok((remote, short_name))
}

fn now_ms() -> u128 {
    UNIX_EPOCH
        .elapsed()
        .expect("system time is set before the Unix epoch")
        .as_millis()
}

async fn handle_git_prompt_push(
    prompt: String,
    askpass: Option<Option<StackId>>,
) -> Option<String> {
    if let Some(branch_id) = askpass {
        tracing::info!("received prompt for branch push {branch_id:?}: {prompt:?}");
        askpass::get_broker()
            .expect("askpass broker must be initialized")
            .submit_prompt(prompt, askpass::Context::Push { branch_id })
            .await
    } else {
        tracing::warn!("received askpass push prompt but no broker was supplied; returning None");
        None
    }
}

async fn handle_git_prompt_fetch(prompt: String, askpass: Option<String>) -> Option<String> {
    if let Some(action) = askpass {
        tracing::info!("received prompt for fetch with action {action:?}: {prompt:?}");
        askpass::get_broker()
            .expect("askpass broker must be initialized")
            .submit_prompt(prompt, askpass::Context::Fetch { action })
            .await
    } else {
        tracing::warn!("received askpass fetch prompt but no broker was supplied; returning None");
        None

View on GitHub (pinned to 58e5313667)