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

  1. Check permissions and ownership of the credentials file/directory; ensure the process user can write it (chown/chmod as needed).
  2. Check free disk space and that the filesystem is not mounted read-only.
  3. Verify HOME/XDG paths resolve to the expected directory when running in containers or CI.
  4. If the file is corrupt, back it up and remove it so a fresh one can be written, then re-login.
  5. 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

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


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/63749b14656ba2bc. Report an issue: GitHub.