xai-org/grok-build · error

failed to start auth provider `{command}`: {e}

Error message

failed to start auth provider `{command}`: {e}

What it means

run_external_auth_provider builds a command for the configured external auth provider and spawns it. This error wraps the std::io::Error returned by cmd.spawn() when the OS cannot launch the provider executable. It means the auth flow itself is fine but the provider command could not be started.

Source

Thrown at crates/codegen/xai-grok-shell/src/auth/flow.rs:210

        over_stale_credential,
        inherit_stderr,
        "auth: running external auth provider (interactive login)"
    );
    let mut cmd = crate::util::subprocess::shell_c(command);
    cmd.stdin(std::process::Stdio::null())
        .stdout(std::process::Stdio::piped())
        .kill_on_drop(true);
    if inherit_stderr {
        cmd.stderr(std::process::Stdio::inherit());
    } else {
        cmd.stderr(std::process::Stdio::piped());
    }
    xai_grok_tools::util::detach_command(&mut cmd);
    cmd.envs(xai_grok_tools::util::pager_env());
    #[allow(clippy::disallowed_methods)]
    let mut child = cmd
        .spawn()
        .map_err(|e| anyhow::anyhow!("failed to start auth provider `{command}`: {e}"))?;
    let stderr_task = if let Some(cb) = on_stderr {
        let stderr = child.stderr.take().expect("stderr was set to piped");
        Some(tokio::task::spawn_local(async move {
            let mut reader = tokio::io::BufReader::new(stderr);
            let mut line = String::new();
            loop {
                line.clear();
                match reader.read_line(&mut line).await {
                    Ok(0) => break,
                    Ok(_) => {
                        let trimmed = line.trim_end();
                        tracing::debug!(line = trimmed, "auth: provider stderr");
                        cb(trimmed);
                    }
                    Err(e) => {
                        tracing::warn!(error = %e, "auth: error reading provider stderr");
                        break;
                    }

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Verify the configured provider command resolves on PATH: `command -v <command>` and install or correct the path in auth config.
  2. Make the provider executable: `chmod +x <script>` and confirm its shebang line exists.
  3. Re-run with the same environment interactively; if it works in a shell but not the app, fix PATH in the app's environment (env vars, shell profile, service unit).
  4. If the provider is a script interpreter issue, check the shebang points to an installed interpreter.

Example fix

// before
authProvider = "my-provider-script"
// after (ensure installed + executable, or use absolute path)
authProvider = "/usr/local/bin/my-provider-script"
Defensive patterns

Strategy: validation

Validate before calling

const cmd = cfg.authProviderCommand;
if (!commandExists(cmd)) {
  throw new Error(`auth provider not found on PATH: ${cmd}`);
}
// shell: command -v "$cmd" >/dev/null || exit 1

Try / catch

match run_auth_flow(...).await {
    Err(e) if e.to_string().contains("failed to start auth provider") => {
        eprintln!("Provider `{}` missing/not executable — check PATH and +x", provider_cmd);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling any login flow (run_auth_flow_steps, mint_session_noninteractive, interactive login) where the configured external auth provider command binary does not exist, is not on PATH, lacks the execute bit, or the working directory/env is unusable so spawn() returns Err.

Common situations: Provider path configured as a bare name not installed; script missing +x after a checkout on a new machine; config points to a binary removed by an upgrade; PATH differs under CI or systemd environments.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/fe2bc4ebc18e31d5. Report an issue: GitHub.