xai-org/grok-build · error
Server returned invalid user_code format (expected [A-Z0-9-]
Error message
Server returned invalid user_code format (expected [A-Z0-9-])
What it means
During OAuth2 device-authorization, the server's user_code is validated to contain only ASCII alphanumerics and hyphens before it is shown to the user. If the issuer returns a user_code with other characters (spaces, control chars, unicode), the client refuses to display it, defending against spoofing/injection from a malicious or buggy issuer.
Source
Thrown at crates/codegen/xai-grok-shell/src/auth/device_code.rs:177
if !resp.status().is_success() {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
if status.as_u16() == 404 {
anyhow::bail!(DeviceCodeError::NotEnabled);
}
anyhow::bail!("Device code request failed (HTTP {status}): {body}");
}
let server_resp: DeviceCodeResponse = resp.json().await?;
// Defend against control characters from a malicious issuer.
if !server_resp
.user_code
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '-')
{
anyhow::bail!("Server returned invalid user_code format (expected [A-Z0-9-])");
}
validate_verification_uri(&server_resp.verification_uri)?;
if let Some(ref verification_uri_complete) = server_resp.verification_uri_complete {
validate_verification_uri(verification_uri_complete)?;
}
Ok(DeviceCode {
verification_uri: server_resp.verification_uri,
verification_uri_complete: server_resp.verification_uri_complete,
user_code: server_resp.user_code,
device_code: server_resp.device_code,
interval: server_resp
.interval
.unwrap_or(DEFAULT_DEVICE_POLL_INTERVAL_SECS),
expires_in: server_resp.expires_in,
})
}View on GitHub (pinned to bc7f02eddd)
Solutions
- Check which authorization server you are hitting (XAI_API_BASE / base URL config) and ensure it is the genuine xAI OAuth2 issuer.
- Inspect the raw device-authorization response (curl -X POST <auth endpoint>/device/code) to see the actual user_code format.
- Update the xai-grok client to a version matching the server's current user_code format.
- If running your own proxy, make it pass through the issuer's user_code unchanged and conform to the expected alphabet.
Example fix
// server/proxy returning spaced user_code
{"user_code": "WDJB MJJT"}
// after: normalize to the expected alphabet
{"user_code": "WDJB-MJJT"} Defensive patterns
Strategy: validation
Validate before calling
fn user_code_ok(code: &str) -> bool {
!code.is_empty()
&& code.chars().all(|c| c.is_ascii_alphanumeric() || c == '-')
}
// call before displaying: if !user_code_ok(&resp.user_code) { abort } Type guard
fn is_safe_user_code(s: &str) -> Option<&str> {
let ok = s.chars().all(|c| c.is_ascii_alphanumeric() || c == '-');
if ok { Some(s) } else { None }
} Try / catch
match request_device_code(&client, &cfg).await {
Ok(resp) => display(resp),
Err(e) if e.to_string().contains("invalid user_code") => {
eprintln!("Issuer returned unusable user_code; verify the auth server URL.");
}
Err(e) => return Err(e),
} Prevention
- Pin the authorization server to the official xAI issuer URL.
- When proxying the device endpoint, pass through user_code untouched.
- Add a response-shape test against your issuer before deploying client updates.
- Log the raw device-authorization response on failure for diagnosis.
When it happens
Trigger: request_device_code receives a device-authorization response whose user_code field contains any character outside [A-Za-z0-9-] (e.g. 'ABCD EFGH', 'ab12_cd', or strings with control characters).
Common situations: Pointing the client at a non-xAI/proxied authorization server with a different user_code alphabet; a server-side regression changing the code format; a misconfigured base URL hitting an unintended endpoint that returns HTML or a different payload shape.
Related errors
- Device code expired. Run `grok login --device-auth` again.
- Authorization denied. The user rejected the request.
- Token exchange error: {detail}
- Server returned invalid verification URI
- Server returned unsupported verification URI scheme
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/e0019cdbc81c2f7d.
Report an issue: GitHub.