xai-org/grok-build · error

external auth provider `{command}`: {e}

Error message

external auth provider `{command}`: {e}

What it means

The provider process ran and produced output, but parse_output() could not turn that output into credentials. The parse error text (from token_output parsing, e.g. 'exited with …', 'produced no output on stdout', 'produced JSON that is not a token payload') is embedded after the command name.

Source

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

                    }
                }
            }
        }))
    } else {
        None
    };
    let output = tokio::time::timeout(
        std::time::Duration::from_secs(300),
        child.wait_with_output(),
    )
    .await
    .map_err(|_| anyhow::anyhow!("external auth provider `{command}` timed out after 300s"))?
    .map_err(|e| anyhow::anyhow!("external auth provider `{command}` IO error: {e}"))?;
    if let Some(task) = stderr_task {
        let _ = task.await;
    }
    let mut auth = parse_output(&output)
        .map_err(|e| anyhow::anyhow!("external auth provider `{command}`: {e}"))?;
    let principal_policy =
        crate::auth::oidc::login_principal_policy(auth_manager.grok_com_config());
    crate::auth::oidc::enforce_login_principal(
        principal_policy.as_ref(),
        crate::auth::oidc::peek_access_token_principal_id(&auth.key).as_deref(),
    )?;
    match (over_stale_credential, auth_manager.current_or_expired()) {
        (true, Some(prev)) => auth.carry_user_profile_from(&prev),
        _ => auth_manager.enrich_auth_inline(&mut auth).await,
    }
    let auth = auth_manager
        .update(auth)
        .await
        .map_err(|e| anyhow::anyhow!("failed to save external auth credentials: {e}"))?;
    tracing::info!(
        user_id = %auth.user_id,
        email = ?auth.email,
        "auth: external provider login complete"

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Run the provider manually and inspect stdout; move human-readable diagnostics to stderr and keep stdout strictly the token.
  2. Ensure the JSON payload includes a non-empty `access_token` (and refresh token only inside JSON, not bare) matching the published contract.
  3. Update the provider to the version matching the shell's expected ExternalAuthOutput schema.
  4. Check provider exit codes: a non-zero exit is reported as 'exited with N'; fix whatever makes the provider fail.

Example fix

// before (provider prints prose + JSON to stdout)
echo "fetching token..."; echo "$JSON"
// after
echo "fetching token..." >&2; printf '%s' "$JSON"
Defensive patterns

Strategy: validation

Validate before calling

const out = execSync(provider_cmd, { encoding: 'utf8' });
if (out.trim().startsWith('{')) {
  const j = JSON.parse(out);
  if (typeof j.access_token !== 'string' || !j.access_token.trim()) {
    throw new Error('provider JSON is not a valid token payload');
  }
}

Type guard

function isTokenPayload(v) {
  return typeof v === 'object' && v !== null &&
    typeof v.access_token === 'string' && v.access_token.trim().length > 0;
}

Try / catch

match run_auth_flow(...).await {
    Err(e) if e.to_string().contains(": produced") || e.to_string().contains("exited with") => {
        eprintln!("Provider output violates the token contract — inspect its stdout");
    }
    other => other?,
}

Prevention

When it happens

Trigger: The provider exits non-zero, prints nothing to stdout, prints non-JSON non-token text, prints JSON that fails ExternalAuthOutput deserialization, or prints JSON with an empty access_token during any external-provider login flow.

Common situations: Provider prints diagnostics to stdout instead of stderr; provider returns an error object like {"error":"expired"} instead of a token payload; provider version changed its output schema (missing access_token or refresh_token fields); wrong credentials cause an HTML/text error page on stdout.

Related errors


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