CherryHQ/cherry-studio · error · Error
Failed to write OAuth storage: ${error instanceof Error ? er
Error message
Failed to write OAuth storage: ${error instanceof Error ? error.message : String(error)} What it means
Thrown by `writeStorage()` when the atomic write (write temp file → rename to final path) fails. The method creates the parent directory, writes to a `.tmp` file, then renames atomically. Any failure in mkdir, writeFile, or rename triggers this. The cache is not updated on failure, so the in-memory state stays consistent with the last successful write.
Source
Thrown at src/main/ai/mcp/oauth/storage.ts:66
private async writeStorage(data: OAuthStorageData): Promise<void> {
try {
// Ensure directory exists
await fs.mkdir(path.dirname(this.filePath), { recursive: true })
// Update timestamp
data.lastUpdated = Date.now()
// Write file atomically
const tempPath = `${this.filePath}.tmp`
await fs.writeFile(tempPath, JSON.stringify(data, null, 2))
await fs.rename(tempPath, this.filePath)
// Update cache
this.cache = data
} catch (error) {
logger.error('Error writing OAuth storage:', error as Error)
throw new Error(`Failed to write OAuth storage: ${error instanceof Error ? error.message : String(error)}`)
}
}
async getClientInformation(): Promise<OAuthClientInformation | undefined> {
const data = await this.readStorage()
return data.clientInfo
}
async saveClientInformation(info: OAuthClientInformationMixed | undefined): Promise<void> {
const data = await this.readStorage()
await this.writeStorage({
...data,
clientInfo: info
})
}
async getTokens(): Promise<OAuthTokens | undefined> {
const data = await this.readStorage()View on GitHub (pinned to 726446b54c)
Solutions
- Check available disk space on the volume containing the MCP config directory
- Verify write permissions on the config directory (usually under userData/mcp/)
- If the rename fails due to cross-filesystem, ensure the .tmp file is created in the same directory as the target (which it is — check for symlink interference)
- Retry the operation — transient I/O errors may resolve; if persistent, investigate disk health
Defensive patterns
Strategy: try-catch
Try / catch
try {
await oauthStorage.saveTokens(tokens)
} catch (e) {
if (e instanceof Error && e.message.startsWith('Failed to write OAuth storage')) {
// Check disk space and permissions, then retry
logger.error('OAuth storage write failed', e)
// Non-fatal: tokens stay in memory, will be retried on next save
}
throw e
} Prevention
- Ensure adequate disk space in the userData directory
- Verify write permissions on the MCP config directory during app startup
- Monitor write failures — if persistent, alert the user about storage issues
When it happens
Trigger: Disk full preventing the temp file write; permission denied on the config directory; the rename fails across filesystems (temp and target on different mounts); the directory was deleted between mkdir and writeFile; disk I/O hardware error.
Common situations: Disk space exhausted; config directory permissions changed since app start; running from a read-only filesystem; antivirus intercepting the rename on Windows; the OS temp directory and config directory are on different volumes making rename fail.
Related errors
- Failed to read OAuth storage: ${error instanceof Error ? err
- Failed to clear OAuth storage: ${error instanceof Error ? er
- No code verifier saved for session
- OAuth authentication failed: ${oauthError instanceof Error ?
- User denied the Feishu app registration
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/3b0fc838d07dbb14.
Report an issue: GitHub.