plandex-ai/plandex · error
refresh failed - save: %w
Error message
refresh failed - save: %w
What it means
refreshCreds wraps an error from SetAccountCredentials after a successful token refresh — the new Claude Max credentials could not be persisted to local account storage. The refresh itself succeeded, so the session works but the new tokens are at risk of not being saved.
Source
Thrown at app/cli/lib/claude_max.go:334
return nil, 0, fmt.Errorf("refresh failed - read body: %w", err)
}
return nil, resp.StatusCode, fmt.Errorf("refresh failed - status %d: %s", resp.StatusCode, b)
}
var r types.OauthResponse
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return nil, 0, fmt.Errorf("refresh failed - decode: %w", err)
}
newCreds := &types.OauthCreds{
OauthResponse: r,
ExpiresAt: time.Now().Add(time.Duration(r.ExpiresIn) * time.Second),
}
// persist updated creds
accountCreds.ClaudeMax = newCreds
if err := SetAccountCredentials(accountCreds); err != nil {
return nil, 0, fmt.Errorf("refresh failed - save: %w", err)
}
return newCreds, resp.StatusCode, nil
}
View on GitHub (pinned to e2d772072e)
Solutions
- Check permissions and ownership of the credentials file/directory; ensure the process user can write it (chown/chmod as needed).
- Check free disk space and that the filesystem is not mounted read-only.
- Verify HOME/XDG paths resolve to the expected directory when running in containers or CI.
- If the file is corrupt, back it up and remove it so a fresh one can be written, then re-login.
- Proceed with the in-memory newCreds even if persistence fails, and log a warning prompting re-auth.
Example fix
// before
if err := SetAccountCredentials(accountCreds); err != nil {
return nil, 0, fmt.Errorf("refresh failed - save: %w", err)
}
// after
if err := SetAccountCredentials(accountCreds); err != nil {
log.Printf("warning: could not persist refreshed credentials: %v; using in-memory creds", err)
return newCreds, resp.StatusCode, nil // still usable this session
} Defensive patterns
Strategy: fallback
Validate before calling
// preflight: can we write where credentials live?
f, err := os.OpenFile(credsPath, os.O_CREATE|os.O_WRONLY, 0o600)
if err != nil {
log.Printf("credential path not writable: %v", err)
}
if f != nil { f.Close() } Try / catch
if err := SetAccountCredentials(accountCreds); err != nil {
log.Printf("warning: persisting refreshed creds failed: %v; continuing with in-memory creds", err)
return newCreds, resp.StatusCode, nil // degrade gracefully
} Prevention
- Ensure the process user owns or can write the credentials directory (check after container/user changes).
- Monitor free disk space where credentials are stored.
- Write atomically (temp file + rename) to avoid corrupt credential files.
- Set HOME explicitly in containers/CI so the path resolves predictably.
When it happens
Trigger: SetAccountCredentials(accountCreds) returns an error while persisting the refreshed OauthCreds — typically a filesystem permission error, read-only disk, corrupt or unwritable credentials file, or serialization failure.
Common situations: Home directory or ~/.config permissions changed (running as a different user/container), disk full or read-only filesystem, credentials file corrupted or locked by another process, or HOME env var unset so the path resolves unexpectedly.
Related errors
- error setting auth: %v
- error writing auth: %v
- error writing auth: %v
- error reading accounts.json: %v
- error storing account: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/63749b14656ba2bc.
Report an issue: GitHub.