openclaw - 💡(How to fix) Fix [Bug]: `openclaw models --agent <id> auth login` writes OAuth tokens to the default agent's profile, ignoring `--agent` [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#73701Fetched 2026-04-29 06:16:12
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Timeline (top)
closed ×1commented ×1

openclaw models --agent <id> auth login --provider <p> silently writes the resulting OAuth credentials to the default agent's auth-profiles.json instead of the agent specified by --agent. The flag is honoured by other paths (e.g. openclaw agent --agent <id> --message ... routes correctly), but the OAuth write path appears to ignore it and resolve to the default agent.

The targeted agent stays on its old (often expired) tokens, while the default agent gets new tokens it didn't ask for. When the default agent's refresh chain consumes the new refresh token, the targeted agent's now-identical refresh token becomes invalid, surfacing as refresh_token_reused.

Error Message

[openai-codex] Token refresh failed: 401 { "code": "refresh_token_reused", "message": "Your refresh token has already been used to generate a new access token. Please try signing in again." } [model-fallback/decision] requested=openai-codex/gpt-5.3-codex candidate=... reason=auth next=none FailoverError: OAuth token refresh failed for openai-codex

Root Cause

openclaw models --agent <id> auth login --provider <p> silently writes the resulting OAuth credentials to the default agent's auth-profiles.json instead of the agent specified by --agent. The flag is honoured by other paths (e.g. openclaw agent --agent <id> --message ... routes correctly), but the OAuth write path appears to ignore it and resolve to the default agent.

The targeted agent stays on its old (often expired) tokens, while the default agent gets new tokens it didn't ask for. When the default agent's refresh chain consumes the new refresh token, the targeted agent's now-identical refresh token becomes invalid, surfacing as refresh_token_reused.

Fix Action

Workaround

Manually copy the freshly written profile entry from the default agent's auth-profiles.json into the targeted agent's file with jq, preserving the rest of the targeted agent's profiles, usageStats, etc.:

jq --slurpfile def agents/default-agent/agent/auth-profiles.json \
   '.profiles["openai-codex:<user>@example.com"] =
       $def[0].profiles["openai-codex:<user>@example.com"]' \
   agents/other-agent/agent/auth-profiles.json > /tmp/merged \
   && mv /tmp/merged agents/other-agent/agent/auth-profiles.json

This works once but is fragile: both agents now share an identical refresh token, and the next refresh by either side invalidates the other. There is no clean way to give a non-default agent its own independent OAuth chain via the supported CLI.

Code Example

{
  "agents": {
    "list": [
      { "id": "default-agent", "agentDir": "/home/user/.openclaw/agents/default-agent/agent",
        "model": "openai-codex/gpt-5.3-codex", "default": true },
      { "id": "other-agent",   "agentDir": "/home/user/.openclaw/agents/other-agent/agent",
        "model": "openai-codex/gpt-5.3-codex" }
    ]
  }
}

---

$ env | grep -E 'OPENCLAW_AGENT_DIR|PI_CODING_AGENT_DIR'   # both empty
$ stat -c '%y %n' agents/default-agent/agent/auth-profiles.json agents/other-agent/agent/auth-profiles.json
# default-agent: <timestamp T0>
# other-agent:   <timestamp T-2hours>

$ openclaw models --agent other-agent auth login --provider openai-codex
# OAuth paste-back flow completes successfully; CLI prints:
#   Updated ~/.openclaw/openclaw.json
#   Auth profile: openai-codex:<user>@example.com (openai-codex/oauth)
#   Default model available: openai-codex/gpt-5.4 ...

$ stat -c '%y %n' agents/default-agent/agent/auth-profiles.json agents/other-agent/agent/auth-profiles.json
# default-agent: <new timestamp T1>   ← rewritten with fresh token
# other-agent:   <timestamp T-2hours>UNCHANGED, still expired

---

user  ...  openclaw  models --agent other-agent auth login --provider openai-codex
user  ...  openclaw-models

---

[openai-codex] Token refresh failed: 401 {
  "code": "refresh_token_reused",
  "message": "Your refresh token has already been used to generate a new access token. Please try signing in again."
}
[model-fallback/decision] requested=openai-codex/gpt-5.3-codex candidate=... reason=auth next=none
FailoverError: OAuth token refresh failed for openai-codex

---

jq --slurpfile def agents/default-agent/agent/auth-profiles.json \
   '.profiles["openai-codex:<user>@example.com"] =
       $def[0].profiles["openai-codex:<user>@example.com"]' \
   agents/other-agent/agent/auth-profiles.json > /tmp/merged \
   && mv /tmp/merged agents/other-agent/agent/auth-profiles.json
RAW_BUFFERClick to expand / collapse

Summary

openclaw models --agent <id> auth login --provider <p> silently writes the resulting OAuth credentials to the default agent's auth-profiles.json instead of the agent specified by --agent. The flag is honoured by other paths (e.g. openclaw agent --agent <id> --message ... routes correctly), but the OAuth write path appears to ignore it and resolve to the default agent.

The targeted agent stays on its old (often expired) tokens, while the default agent gets new tokens it didn't ask for. When the default agent's refresh chain consumes the new refresh token, the targeted agent's now-identical refresh token becomes invalid, surfacing as refresh_token_reused.

Version

OpenClaw 2026.4.2 (d74a122) (npm install on Ubuntu 24.04, kernel 6.17).

Steps to reproduce

Two agents in ~/.openclaw/openclaw.json, both targeting the same Codex provider, with default-agent marked default and other-agent not default:

{
  "agents": {
    "list": [
      { "id": "default-agent", "agentDir": "/home/user/.openclaw/agents/default-agent/agent",
        "model": "openai-codex/gpt-5.3-codex", "default": true },
      { "id": "other-agent",   "agentDir": "/home/user/.openclaw/agents/other-agent/agent",
        "model": "openai-codex/gpt-5.3-codex" }
    ]
  }
}

Both agents have a per-agent auth-profiles.json with an existing openai-codex:<user>@example.com profile. other-agent has expired tokens; default-agent has valid (old) tokens.

$ env | grep -E 'OPENCLAW_AGENT_DIR|PI_CODING_AGENT_DIR'   # both empty
$ stat -c '%y %n' agents/default-agent/agent/auth-profiles.json agents/other-agent/agent/auth-profiles.json
# default-agent: <timestamp T0>
# other-agent:   <timestamp T-2hours>

$ openclaw models --agent other-agent auth login --provider openai-codex
# OAuth paste-back flow completes successfully; CLI prints:
#   Updated ~/.openclaw/openclaw.json
#   Auth profile: openai-codex:<user>@example.com (openai-codex/oauth)
#   Default model available: openai-codex/gpt-5.4 ...

$ stat -c '%y %n' agents/default-agent/agent/auth-profiles.json agents/other-agent/agent/auth-profiles.json
# default-agent: <new timestamp T1>   ← rewritten with fresh token
# other-agent:   <timestamp T-2hours> ← UNCHANGED, still expired

ps -ef during the flow confirms the launched process did receive --agent other-agent:

user  ...  openclaw  models --agent other-agent auth login --provider openai-codex
user  ...  openclaw-models

After the flow, decoding the access JWTs confirms the new token landed in the default agent's profile:

FileexpiresAccess JWT iat
agents/default-agent/agent/auth-profiles.jsonrecent (one week out)matches flow time
agents/other-agent/agent/auth-profiles.jsonalready expiredunchanged

openclaw agent --agent other-agent --message ... does route correctly to the other agent's workspace and (now stale) profile, so --agent is honoured by that path — it's specifically the models auth login write target that's wrong.

Expected behaviour

openclaw models --agent <id> auth login --provider <p> should write the resulting tokens to ${agents.list[id=<id>].agentDir}/auth-profiles.json, not to the default agent's. The Updated ~/.openclaw/openclaw.json and Auth profile: … confirmation lines suggest the CLI thinks it succeeded, so the bug is in the resolution of which auth-profiles.json to mutate.

Actual behaviour

Tokens land in the default agent's profile regardless of --agent. The targeted agent stays on stale credentials, and once the default agent uses its new refresh token, the targeted agent fails with:

[openai-codex] Token refresh failed: 401 {
  "code": "refresh_token_reused",
  "message": "Your refresh token has already been used to generate a new access token. Please try signing in again."
}
[model-fallback/decision] requested=openai-codex/gpt-5.3-codex candidate=... reason=auth next=none
FailoverError: OAuth token refresh failed for openai-codex

Workaround

Manually copy the freshly written profile entry from the default agent's auth-profiles.json into the targeted agent's file with jq, preserving the rest of the targeted agent's profiles, usageStats, etc.:

jq --slurpfile def agents/default-agent/agent/auth-profiles.json \
   '.profiles["openai-codex:<user>@example.com"] =
       $def[0].profiles["openai-codex:<user>@example.com"]' \
   agents/other-agent/agent/auth-profiles.json > /tmp/merged \
   && mv /tmp/merged agents/other-agent/agent/auth-profiles.json

This works once but is fragile: both agents now share an identical refresh token, and the next refresh by either side invalidates the other. There is no clean way to give a non-default agent its own independent OAuth chain via the supported CLI.

Related

  • #40402 — --profile-id flag for models auth login (same family of issue: the CLI's profile-write target isn't fully addressable).
  • #43681 — OAuth rotation for same model provider across multiple subscriptions (would be much simpler if --agent worked).

Suggested fix

In whichever code path resolves the auth-profiles.json target during models auth login, honour the same --agent resolution used by openclaw agent --agent <id> ... (look up agents.list[].agentDir for the given id) before falling back to the default agent / OPENCLAW_AGENT_DIR.

extent analysis

TL;DR

The most likely fix is to modify the code path that resolves the auth-profiles.json target during models auth login to honor the --agent flag.

Guidance

  • Identify the code responsible for resolving the auth-profiles.json target during models auth login and modify it to use the --agent flag to determine the correct agent directory.
  • Verify that the --agent flag is being passed correctly to the models auth login command and that the agent directory is being resolved correctly.
  • Test the modified code to ensure that the resulting tokens are written to the correct auth-profiles.json file.
  • Consider adding additional logging or debugging statements to help identify any issues with the --agent flag or agent directory resolution.

Example

No code snippet is provided as the issue does not contain sufficient information about the codebase.

Notes

The provided workaround using jq to manually copy the profile entry is fragile and may not be suitable for long-term use. A proper fix should be implemented to ensure that the --agent flag is honored correctly.

Recommendation

Apply a workaround by manually modifying the auth-profiles.json file until a proper fix can be implemented. However, the recommended long-term solution is to modify the code to honor the --agent flag correctly.

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…

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]: `openclaw models --agent <id> auth login` writes OAuth tokens to the default agent's profile, ignoring `--agent` [1 comments, 2 participants]