Skip to content

OAuth renewal doesn't update auth-profiles.provisioned.json, causing recovery loops #38336

@dfrysinger

Description

@dfrysinger

Summary

When OAuth tokens are renewed via openclaw onboard, the token is saved to auth-profiles.json (live copy) but NOT to auth-profiles.provisioned.json (golden copy). This causes safe-mode recovery to repeatedly fail because it reads from the golden copy.

The Architecture

~/.openclaw/agents/main/agent/auth-profiles.json            # Live copy (gateway reads/writes)
~/.openclaw/agents/main/agent/auth-profiles.provisioned.json # Golden copy (recovery reads)

From build-full-config.sh (lines 275-279):

# Golden copy — never modified by gateway, survives shutdown persistence clobber.
# Safe mode recovery reads from this to find OAuth tokens that may have been
# dropped from the live copy during gateway restart cycles.
# NOTE: This is static after provisioning. If credentials are rotated at runtime
# (e.g., OAuth token refresh), re-run build-full-config.sh to update the golden copy.

From safe-mode-recovery.sh (lines 192-200):

# Find auth-profiles.json — prefer golden provisioned copy (survives gateway
# SIGTERM persistence clobber), fall back to live copy if golden doesn't exist.
for path in \
  "$home/.openclaw/agents/main/agent/auth-profiles.provisioned.json" \
  "$home/.openclaw/agents/main/agent/auth-profiles.json" \
  ...

The Problem

  1. User runs openclaw onboard --auth-choice openai-codex
  2. OAuth flow completes, token saved to auth-profiles.json
  3. auth-profiles.provisioned.json is NOT updated ❌
  4. Later, something triggers safe-mode recovery
  5. Recovery reads from .provisioned.json (stale token)
  6. Recovery thinks OAuth is broken → stays in safe mode
  7. User re-runs OAuth → same loop repeats

Current Workaround

After OAuth renewal, manually copy live → golden:

cp ~/.openclaw/agents/main/agent/auth-profiles.json \
   ~/.openclaw/agents/main/agent/auth-profiles.provisioned.json

Proposed Fix

Option A: Update openclaw onboard to sync golden copy

When openclaw onboard successfully saves OAuth credentials, also update the provisioned copy:

// After writing auth-profiles.json
const provisionedPath = path.join(agentDir, 'auth-profiles.provisioned.json');
if (fs.existsSync(provisionedPath)) {
  fs.copyFileSync(authProfilesPath, provisionedPath);
}

Option B: Document the manual step

Add to safe-mode agent TOOLS.md and main docs:

  • Explain the two-file architecture
  • Document the manual copy step after OAuth renewal

Context

This was discovered during a multi-hour safe-mode debugging session where:

  • Discord tokens were fixed in both habitat-parsed.env and openclaw.full.json
  • OpenAI OAuth was renewed multiple times via openclaw onboard
  • Recovery kept reverting to safe mode because .provisioned.json had stale token

Related issue: #37659 (other safe-mode documentation gaps)

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions