zeroclaw-labs/zeroclaw · error

No OAuth code provided

Error message

No OAuth code provided

What it means

parse_code_from_redirect trims its input and bails immediately when the result is empty. The function accepts a full callback URL, a bare query string, or a raw authorization code, so an all-whitespace input is the one case it can definitively reject as 'nothing was provided'. It is reached via receive_code_from_stdin (user pressed Enter on an empty line) and via parse_code_from_url/parse_code_from_raw wrappers.

Source

Thrown at crates/zeroclaw-providers/src/auth/gemini_oauth.rs:492

            WARN,
            ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
                .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                .with_attrs(::serde_json::json!({
                    "oauth_provider": "gemini",
                    "missing": "state",
                })),
            "gemini_oauth: callback missing state parameter"
        );
        anyhow::Error::msg("No 'state' parameter in callback")
    })?;

    Ok((code, state))
}

pub fn parse_code_from_redirect(input: &str, expected_state: Option<&str>) -> Result<String> {
    let trimmed = input.trim();
    if trimmed.is_empty() {
        anyhow::bail!("No OAuth code provided");
    }

    // Extract query string
    let query = if let Some((_, right)) = trimmed.split_once('?') {
        right
    } else {
        trimmed
    };

    let params = parse_query_params(query);

    // If we have code param, extract it
    if let Some(code) = params.get("code") {
        // Validate state if expected
        if let Some(expected) = expected_state
            && let Some(actual) = params.get("state")
            && actual != expected
        {

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Paste the full callback URL (http://localhost:1456/auth/callback?code=...&state=...) or just the raw code, then press Enter
  2. If scripting the input, guard that the variable is non-empty before piping it to the prompt

Example fix

// before
let code = parse_code_from_redirect(&input, Some(&state))?; // input may be empty

// after
let input = input.trim();
if input.is_empty() {
    anyhow::bail!("paste the full callback URL or the raw authorization code");
}
let code = parse_code_from_redirect(input, Some(&state))?;
Defensive patterns

Strategy: validation

Validate before calling

let trimmed = input.trim();
if trimmed.is_empty() {
    eprintln!("nothing was pasted; paste the full callback URL or the raw code");
    return;
}
let code = parse_code_from_redirect(trimmed, Some(&expected_state))?;

Try / catch

if let Err(e) = parse_code_from_redirect(&raw, expected_state) {
    if e.to_string() == "No OAuth code provided" {
        // re-prompt the user instead of failing the whole login
        continue;
    }
    return Err(e);
}

Prevention

When it happens

Trigger: The stdin fallback prompt is shown (loopback bind failed or callback timed out) and the user hits Enter without typing anything; a caller passes an empty string or whitespace-only string to parse_code_from_redirect, parse_code_from_url, or parse_code_from_raw.

Common situations: Headless/remote login where the user presses Enter accidentally; an automation script feeds an unset environment variable or empty clipboard content into the paste prompt.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/a8b2131279d30ade. Report an issue: GitHub.