warpdotdev/warp · error · anyhow::Error

Unexpected non-terminal OAuth status returned

Error message

Unexpected non-terminal OAuth status returned

What it means

Thrown after the OAuth polling helper `poll_oauth_until_terminal` resolves with `OauthConnectTxStatus::Pending` or `InProgress`. That helper is contractually required to keep polling until a terminal status (Completed/Failed/Expired), so a non-terminal result means an internal invariant broke. The app force-terminates (TerminationMode::ForceTerminate) rather than continue in an undefined state.

Source

Thrown at app/src/ai/agent_sdk/integration.rs:322

                                            }
                                            Ok(OauthConnectTxStatus::Failed) => {
                                                ctx.terminate_app(
                                                    TerminationMode::ForceTerminate,
                                                    Some(Err(anyhow::anyhow!("OAuth authorization failed."))),
                                                );
                                            }
                                            Ok(OauthConnectTxStatus::Expired) => {
                                                ctx.terminate_app(
                                                    TerminationMode::ForceTerminate,
                                                    Some(Err(anyhow::anyhow!("OAuth authorization expired."))),
                                                );
                                            }
                                            Ok(OauthConnectTxStatus::Pending)
                                            | Ok(OauthConnectTxStatus::InProgress) => {
                                                // Should not be returned by poll_oauth_until_terminal.
                                                ctx.terminate_app(
                                                    TerminationMode::ForceTerminate,
                                                    Some(Err(anyhow::anyhow!("Unexpected non-terminal OAuth status returned"))),
                                                );
                                            }
                                            Err(err) => {
                                                ctx.terminate_app(
                                                    TerminationMode::ForceTerminate,
                                                    Some(Err(anyhow::anyhow!("Error polling OAuth status: {err}"))),
                                                );
                                            }
                                        }
                                    },
                                );
                            }
                            (Some(auth_url), None) => {
                                println!("Authorize the provider here: {auth_url}\n");
                                ctx.open_url(&auth_url);
                                println!(
                                    "After authorizing, re-run the command to continue the integration {action} process.",
                                );

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Inspect poll_oauth_until_terminal in app/src/ai/agent_sdk/integration.rs and confirm it only resolves on Completed/Failed/Expired.
  2. If a new OauthConnectTxStatus variant was added, classify it as non-terminal (keep polling) in the loop predicate.
  3. Re-run the integration command once — a transient server-side race can surface this branch.
  4. If unmodified code hits it, capture logs and file it as a client bug with the tx_id.

Example fix

// before
let status = client.get_oauth_tx(tx_id).await?;
if status != OauthConnectTxStatus::InProgress {
    return Ok(status);
}
// after
let status = client.get_oauth_tx(tx_id).await?;
match status {
    OauthConnectTxStatus::Pending | OauthConnectTxStatus::InProgress => continue,
    terminal => return Ok(terminal),
}
Defensive patterns

Strategy: retry

Try / catch

In the spawned callback, match the poll Result; on the Ok(Pending|InProgress) arm, re-enter start_create_or_update_flow once (bounded by the existing attempt counter) instead of terminating, and only ForceTerminate when the budget is exhausted.

Prevention

When it happens

Trigger: Running the agent-sdk `integration create/update` flow where the server returns both auth_url and tx_id: the client opens the browser, polls the transaction, and the polling future resolves successfully — not with Err — while the status is still Pending or InProgress. Typically a bug in poll_oauth_until_terminal's terminal predicate or a new enum variant it does not classify.

Common situations: A local refactor of poll_oauth_until_terminal that returns early; a newly added OauthConnectTxStatus variant the loop treats as final; a race where the poll loop's last response is non-final but the future completes anyway.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/8a11e20442231041. Report an issue: GitHub.