{"record":{"id":"5321adec2adfd069","repo":"gitbutlerapp/gitbutler","slug":"askpass-broker-must-be-initialized","errorCode":null,"errorMessage":"askpass broker must be initialized","messagePattern":"askpass broker must be initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/legacy/askpass.rs","lineNumber":15,"sourceCode":"//! In place of commands.rs\nuse anyhow::anyhow;\nuse but_askpass::{self as askpass, AskpassRequestId};\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct SubmitPromptResponseParams {\n    pub id: AskpassRequestId,\n    pub response: Option<String>,\n}\n\npub async fn submit_prompt_response(params: SubmitPromptResponseParams) -> anyhow::Result<()> {\n    askpass::get_broker()\n        .ok_or(anyhow!(\"askpass broker must be initialized\"))?\n        .handle_response(params.id, params.response)\n        .await;\n    Ok(())\n}\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-api/src/legacy/askpass.rs#L1-L20","documentation":"submit_prompt_response() delivers a user's answer to a pending credential prompt through the process-global askpass broker. get_broker() yields Some only when the host called but_askpass::try_init()/init() at startup (GUI mode); it yields None when the broker was explicitly disabled (CLI mode). Submitting a response with no active broker is rejected.","triggerScenarios":"Invoking the submitPromptResponse command in a host that ran but_askpass::disable() (CLI configuration) or never initialized the broker before the first credential-needing operation; a delayed frontend response arriving in a host that does not own the broker.","commonSituations":"Embedding but-api in a custom host without the startup init sequence; tests invoking the command directly; CLI and GUI processes sharing a frontend event stream.","solutions":["Call but_askpass::try_init(submit_prompt_callback) exactly once during host startup, before any fetch/push that can prompt","Do not route submitPromptResponse to a host that disabled the broker; treat it as a no-op in CLI hosts","In tests, initialize (or explicitly disable and assert on) the broker before invoking the command"],"exampleFix":"// before: host never configures askpass; later submit_prompt_response fails\n// with 'askpass broker must be initialized'\n\n// after: configure once at startup\nbut_askpass::try_init(move |prompt| {\n    forward_prompt_to_ui(prompt); // GUI callback\n}).expect(\"broker configured once at startup\");","handlingStrategy":"validation","validationCode":"match but_askpass::try_get_broker() {\n    Some(Some(_)) => { /* broker active: safe to submit */ }\n    Some(None) => { /* broker disabled (CLI): ignore the submission */ }\n    None => { /* host bug: call but_askpass::try_init() at startup */ }\n}","typeGuard":"fn askpass_ready() -> bool {\n    matches!(but_askpass::try_get_broker(), Some(Some(_)))\n}","tryCatchPattern":"if let Err(err) = submit_prompt_response(params).await {\n    if err.to_string().contains(\"askpass broker must be initialized\") {\n        // drop the stale prompt UI; re-auth will raise a fresh prompt\n    }\n}","preventionTips":["Initialize the askpass broker in the host startup sequence before any networked git operation","Only show prompt UI when the host actually owns the broker","Treat late prompt responses as no-ops in disabled (CLI) hosts"],"tags":["askpass","authentication","credentials","initialization","startup"],"backgroundTag":"service-not-initialized","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}