openclaw - 💡(How to fix) Fix [Bug]: pi-ai getAccountId returns null after Codex token refresh — Codex harness via codex/gpt-* fails with "Failed to extract accountId from token" [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#77108Fetched 2026-05-05 05:52:02
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
2
Author
Timeline (top)
closed ×1commented ×1labeled ×1mentioned ×1

When the codex plugin's synthetic auth refreshes the openai-codex OAuth token, pi-ai's getAccountId() returns null and the harness throws Failed to extract accountId from token; there is no openclaw models auth login --provider codex flow to recover.

Error Message

FailoverError: Failed to extract accountId from token provider=codex model=gpt-5.5 reason=auth

Root Cause

  1. Install and activate @openclaw/[email protected].
  2. Configure an agent with model: "codex/gpt-5.5" (the deprecated form, used because the documented openai/* form is blocked by a separate issue).
  3. Restart the gateway.
  4. Run openclaw agent --agent main --message "test".

Code Example

FailoverError: Failed to extract accountId from token
provider=codex model=gpt-5.5 reason=auth

---

$ openclaw models auth login --provider codex
Error: No provider plugins found. Install one via `openclaw plugins install`.

---

Source location — node_modules/@mariozechner/pi-ai/dist/utils/oauth/openai-codex.js:

function getAccountId(accessToken) {
    const payload = decodeJwt(accessToken);
    const auth = payload?.[JWT_CLAIM_PATH];
    const accountId = auth?.chatgpt_account_id;
    return typeof accountId === "string" && accountId.length > 0 ? accountId : null;
}

Throws at :323 (initial token exchange success path) and :346 (refresh path):

const accountId = getAccountId(result.access);
if (!accountId) {
    throw new Error("Failed to extract accountId from token");
}

Trajectory record:
{
  "fallbackStepFromModel":          "codex/gpt-5.5",
  "fallbackStepFromFailureReason":  "auth",
  "fallbackStepFromFailureDetail":  "Failed to extract accountId from token",
  "fallbackStepFinalOutcome":       "chain_exhausted"
}
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

When the codex plugin's synthetic auth refreshes the openai-codex OAuth token, pi-ai's getAccountId() returns null and the harness throws Failed to extract accountId from token; there is no openclaw models auth login --provider codex flow to recover.

Steps to reproduce

  1. Install and activate @openclaw/[email protected].
  2. Configure an agent with model: "codex/gpt-5.5" (the deprecated form, used because the documented openai/* form is blocked by a separate issue).
  3. Restart the gateway.
  4. Run openclaw agent --agent main --message "test".

Expected behavior

The codex plugin uses the existing openai-codex:default OAuth profile (which has valid accountId, access, refresh fields), refreshes the token if needed, and serves the agent turn.

Actual behavior

The refresh is attempted; the response token is rejected by getAccountId() because chatgpt_account_id is missing at the expected JWT claim path. Error:

FailoverError: Failed to extract accountId from token
provider=codex model=gpt-5.5 reason=auth

Attempting manual recovery via the standard CLI fails:

$ openclaw models auth login --provider codex
Error: No provider plugins found. Install one via `openclaw plugins install`.

(The codex plugin IS installed and active — but auth login doesn't surface it because the manifest declares syntheticAuthRefs: ["codex"], i.e. synthetic-only auth.)

OpenClaw version

2026.5.2 (8b2a6e5)

Operating system

macOS 26.2 (arm64)

Install method

pnpm (global)

Model

codex/gpt-5.5

Provider / routing chain

openclaw -> codex plugin -> pi-ai openai-codex OAuth refresh -> Codex token endpoint -> response missing chatgpt_account_id at JWT_CLAIM_PATH

Additional provider/model setup details

~/.codex/auth.json present (auth_mode chatgpt, last_refresh 2026-04-29, top-level account_id populated). Existing openai-codex:default OAuth profile in ~/.openclaw/agents/main/agent/auth-profiles.json has populated accountId, valid access JWT (decodes to a payload with https://api.openai.com/auth.chatgpt_account_id populated), valid refresh, and future expires. Bug is specific to the refresh response, not initial issuance.

Logs, screenshots, and evidence

Source location — node_modules/@mariozechner/pi-ai/dist/utils/oauth/openai-codex.js:

function getAccountId(accessToken) {
    const payload = decodeJwt(accessToken);
    const auth = payload?.[JWT_CLAIM_PATH];
    const accountId = auth?.chatgpt_account_id;
    return typeof accountId === "string" && accountId.length > 0 ? accountId : null;
}

Throws at :323 (initial token exchange success path) and :346 (refresh path):

const accountId = getAccountId(result.access);
if (!accountId) {
    throw new Error("Failed to extract accountId from token");
}

Trajectory record:
{
  "fallbackStepFromModel":          "codex/gpt-5.5",
  "fallbackStepFromFailureReason":  "auth",
  "fallbackStepFromFailureDetail":  "Failed to extract accountId from token",
  "fallbackStepFinalOutcome":       "chain_exhausted"
}

Impact and severity

Affected: any user attempting the codex/gpt-* (deprecated) Codex harness route whose token requires refresh. Severity: Hard block for the Codex harness use case. Combined with the agentRuntime issue (which blocks the documented openai/* route), there is no working path to enable the Codex harness today. Frequency: 100% — every harness attempt that triggers refresh. Consequence: Codex harness unreachable; no CLI recovery flow because of synthetic-only auth design.

Additional information

Since pi-ai is a separate package (@mariozechner/pi-ai), the primary fix likely needs to land there and ship via OpenClaw's dependency bump.

Possible fix directions (NOT_ENOUGH_INFO to choose between them without inspecting a refreshed token's claim structure):

  • Fall back to credential.accountId (already populated on the stored profile) when JWT extraction returns null.
  • Try alternative claim paths (payload.chatgpt_account_id, top-level account_id) before throwing.

Secondary UX fix: expose openclaw models auth login --provider codex as a passthrough that triggers the synthetic refresh and surfaces errors verbosely, OR document the synthetic-only behavior so users don't chase a non-existent flow.

I have a refreshed token I can decode and share the (sanitized) JWT claim structure if useful for diagnosis

extent analysis

TL;DR

The most likely fix involves modifying the getAccountId function in @mariozechner/pi-ai to handle cases where the chatgpt_account_id is missing from the JWT claim path.

Guidance

  • Inspect the refreshed token's claim structure to determine the correct path for extracting the accountId.
  • Consider falling back to credential.accountId when JWT extraction returns null to ensure a valid accountId is used.
  • Alternative claim paths such as payload.chatgpt_account_id or top-level account_id could be tried before throwing an error.
  • Expose openclaw models auth login --provider codex as a passthrough to trigger synthetic refresh and surface errors verbosely.

Example

function getAccountId(accessToken) {
    const payload = decodeJwt(accessToken);
    const auth = payload?.[JWT_CLAIM_PATH];
    const accountId = auth?.chatgpt_account_id || payload?.chatgpt_account_id || payload?.account_id;
    return typeof accountId === "string" && accountId.length > 0 ? accountId : credential.accountId;
}

Notes

The fix requires inspecting the refreshed token's claim structure to determine the correct path for extracting the accountId. The provided example is a possible solution but may need to be adjusted based on the actual claim structure.

Recommendation

Apply a workaround by modifying the getAccountId function to handle missing chatgpt_account_id claims, as this will allow the Codex harness to function until a permanent fix is implemented in @mariozechner/pi-ai.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The codex plugin uses the existing openai-codex:default OAuth profile (which has valid accountId, access, refresh fields), refreshes the token if needed, and serves the agent turn.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: pi-ai getAccountId returns null after Codex token refresh — Codex harness via codex/gpt-* fails with "Failed to extract accountId from token" [1 comments, 2 participants]