moeru-ai/airi · error · Error
${openResult}
Error message
${openResult} What it means
Thrown by the electronAppOpenUserDataFolder IPC handler. Electron's shell.openPath(path) returns an empty string on success and a non-empty error message string on failure; the handler throws that message verbatim. So the error text is OS-supplied (e.g. 'Failed to open path') rather than a hardcoded constant.
Source
Thrown at apps/stage-tamagotchi/src/main/services/electron/app.ts:18
import type { createContext } from '@moeru/eventa/adapters/electron/main'
import type { BrowserWindow } from 'electron'
import { defineInvokeHandler } from '@moeru/eventa'
import { app, shell } from 'electron'
import { isLinux, isMacOS, isWindows } from 'std-env'
import { electron, electronAppOpenUserDataFolder, electronAppQuit } from '../../../shared/eventa'
export function createAppService(params: { context: ReturnType<typeof createContext>['context'], window: BrowserWindow }) {
defineInvokeHandler(params.context, electron.app.isMacOS, () => isMacOS)
defineInvokeHandler(params.context, electron.app.isWindows, () => isWindows)
defineInvokeHandler(params.context, electron.app.isLinux, () => isLinux)
defineInvokeHandler(params.context, electronAppOpenUserDataFolder, async () => {
const path = app.getPath('userData')
const openResult = await shell.openPath(path)
if (openResult) {
throw new Error(openResult)
}
return { path }
})
defineInvokeHandler(params.context, electronAppQuit, () => app.quit())
}
View on GitHub (pinned to 27111382b4)
Solutions
- Ensure app.getPath('userData') exists before calling openPath — mkdir it if missing.
- Check OS file associations for directory opening (xdg-open on Linux, Finder on macOS).
- On Linux, verify xdg-utils is installed and XDG_CURRENT_DESKTOP is set.
- Run the app outside a locked-down sandbox that blocks process spawning.
Example fix
// before
const path = app.getPath('userData')
const openResult = await shell.openPath(path)
if (openResult) {
throw new Error(openResult)
}
// after
const path = app.getPath('userData')
await fs.promises.mkdir(path, { recursive: true })
const openResult = await shell.openPath(path)
if (openResult) {
throw new Error(`Could not open user data folder: ${openResult}`)
} Defensive patterns
Strategy: try-catch
Validate before calling
import { existsSync, mkdirSync } from 'node:fs'
import { app } from 'electron'
function ensureUserDataFolder(): string {
const path = app.getPath('userData')
if (!existsSync(path)) mkdirSync(path, { recursive: true })
return path
} Try / catch
try {
await invokeOpenUserDataFolder()
} catch (e) {
// e.message is OS-supplied; surface to user, suggest manual path
showError(`Could not open the folder automatically. Open it manually: ${app.getPath('userData')}`)
} Prevention
- Create userData with mkdir recursive before openPath.
- Provide a fallback 'copy path' button when openPath fails.
- Verify OS screen-recording/file-manager associations on Linux.
When it happens
Trigger: User clicks 'Open User Data Folder' in settings; the userData directory does not exist yet, has been deleted, has restrictive permissions, or no application is registered to open a folder on the OS.
Common situations: First run before userData was created; folder moved/deleted externally; Linux without a file manager handler; permissions locked by another process; sandboxed environment blocking shell.openPath.
Related errors
- Failed to apply server channel configuration
- Invalid Godot stage scene input payload.
- Unable to locate engines/stage-tamagotchi-godot/project.godo
- Godot stage is not running.
- Godot stage bridge is not connected.
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/c403663883319b42.
Report an issue: GitHub.