{"record":{"id":"2fb8496661f12062","repo":"xai-org/grok-build","slug":"failed-to-fetch-billing-data-e","errorCode":null,"errorMessage":"Failed to fetch billing data: {e}","messagePattern":"Failed to fetch billing data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-shell/src/extensions/billing.rs","lineNumber":239,"sourceCode":"        .header(\"x-grok-client-version\", xai_grok_version::VERSION)\n        .header(\n            crate::http::CLIENT_MODE_HEADER,\n            crate::http::process_client_mode(),\n        )\n        .timeout(std::time::Duration::from_secs(15))\n        .send()\n        .await\n        .map_err(|e| {\n            tracing::error!(error = %e, \"billing: upstream request failed\");\n            xai_grok_telemetry::unified_log::warn(\n                \"billing: upstream request failed\",\n                None,\n                Some(serde_json::json!({ \"error\": e.to_string() })),\n            );\n            acp::Error::internal_error().data(format!(\"Failed to fetch billing data: {e}\"))\n        })?;\n\n    if !credits_resp.status().is_success() {\n        let status = credits_resp.status().as_u16();\n        let body = credits_resp.text().await.unwrap_or_default();\n        tracing::warn!(status, url = %credits_url, \"billing: upstream error\");\n\n        let detail = serde_json::from_str::<serde_json::Value>(&body)\n            .ok()\n            .and_then(|v| v.get(\"error\").and_then(|e| e.as_str()).map(String::from))\n            .unwrap_or_else(|| format!(\"HTTP {status}\"));\n\n        xai_grok_telemetry::unified_log::warn(\n            \"billing: upstream error\",\n            None,\n            Some(serde_json::json!({\n                \"status\": status,\n                \"detail\": detail,\n            })),\n        );\n","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-shell/src/extensions/billing.rs#L221-L257","documentation":"The billing extension in xai-grok-shell fetches credits/billing data from an upstream HTTP endpoint. If the request itself fails (network error, DNS, TLS), the handler converts the error into an ACP `internal_error` carrying 'Failed to fetch billing data: {e}'. The error text is also reported via telemetry with the upstream error attached as data.","triggerScenarios":"`credits_resp` future resolves with `Err(e)` from the HTTP client — connection refused/timeout to the billing endpoint, DNS failure, TLS handshake error, or reqwest client misconfiguration — inside `handle_get_billing`.","commonSituations":"Offline machine or corporate proxy blocking the billing host; wrong API base URL in remote settings; expired/rotated credentials causing TLS or auth-layer connection resets; firewall in CI preventing egress.","solutions":["Check network connectivity/proxy settings for the billing endpoint host; set HTTPS_PROXY if behind a corporate proxy.","Read `{e}` (also present in the ACP error data) to identify the specific reqwest failure and fix accordingly.","Verify the configured billing/credits URL in remote settings is correct and reachable (curl it from the same host).","Retry after transient network issues; if persistent, check status.x.ai or internal service health for the billing service."],"exampleFix":"// before: no proxy configured in an air-gapped env\nlet resp = client.get(credits_url).send().await?;\n// after: configure proxy/env or fail fast with connectivity check\nexport HTTPS_PROXY=http://proxy.corp:8080\nlet resp = client.get(credits_url).send().await?;","handlingStrategy":"retry","validationCode":"// check the endpoint is reachable before invoking the billing handler\nconst ok = await fetch(creditsUrl, { method: \"HEAD\" }).then(r => r.ok).catch(() => false);\nif (!ok) console.warn(\"billing endpoint unreachable; expect Failed to fetch billing data\");","typeGuard":null,"tryCatchPattern":"try {\n  const billing = await acp.request(\"billing_get\");\n} catch (e) {\n  if (String(e.message).startsWith(\"Failed to fetch billing data\")) {\n    await backoffRetry(() => acp.request(\"billing_get\"), 3); // transient network?\n  } else { throw e; }\n}","preventionTips":["Set HTTPS_PROXY/HTTP_PROXY in restricted networks","Verify the billing base URL in remote settings is reachable from the host","Retry with exponential backoff for transient network faults","Monitor egress/DNS health in CI environments"],"tags":["http","network","billing","reqwest"],"backgroundTag":"http-request-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}