stablyai/orca · error · RuntimeClientError
runtime_error
runtime_error
Error message
Could not read ${dataPath}: ${error instanceof Error ? error.message : String(error)} What it means
Wrapped RuntimeClientError (code 'runtime_error') thrown by readPersistedState when reading/parsing the agent-hooks state file throws for any reason — a JSON SyntaxError, the not-an-object inner Error (538), or a filesystem read error. It prefixes the message with the dataPath and the underlying error message so the user knows which file failed and why. The original cause is stringified into the message (not chained via .cause).
Source
Thrown at src/cli/handlers/agent-hooks.ts:47
return join(getDefaultUserDataPath(), 'orca-data.json')
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}
function readPersistedState(dataPath: string): PersistedState {
if (!existsSync(dataPath)) {
return getDefaultPersistedState(homedir())
}
try {
const parsed = JSON.parse(readFileSync(dataPath, 'utf-8'))
if (!isRecord(parsed)) {
throw new Error('file does not contain a JSON object')
}
return parsed as PersistedState
} catch (error) {
throw new RuntimeClientError(
'runtime_error',
`Could not read ${dataPath}: ${error instanceof Error ? error.message : String(error)}`
)
}
}
function writePersistedState(dataPath: string, state: PersistedState): void {
mkdirSync(dirname(dataPath), { recursive: true })
const tmpPath = join(dirname(dataPath), `.${Date.now()}-${randomUUID()}.tmp`)
let renamed = false
try {
writeFileSync(tmpPath, `${JSON.stringify(state, null, 2)}\n`, 'utf-8')
renameSync(tmpPath, dataPath)
renamed = true
} finally {
if (!renamed && existsSync(tmpPath)) {
try {
unlinkSync(tmpPath)View on GitHub (pinned to 1136503c6a)
Solutions
- Read the embedded underlying message to classify: SyntaxError => corrupt JSON, EACCES => permissions, EISDIR => path is a dir.
- Back up then delete the corrupt file so the next run regenerates defaults.
- Fix permissions/ownership on the file if the cause is EACCES.
- Confirm writePersistedState's atomic-rename path is on the same filesystem to avoid partial writes.
Example fix
// before: corrupt ~/.config/orca/agent-hooks.json -> runtime_error // after mv ~/.config/orca/agent-hooks.json ~/.config/orca/agent-hooks.json.bak # next run recreates a valid default state
Defensive patterns
Strategy: try-catch
Validate before calling
import { readFileSync, existsSync, statSync } from 'node:fs'
function safeReadState(dataPath: string): string {
if (!existsSync(dataPath)) throw new Error('missing')
const st = statSync(dataPath)
if (!st.isFile()) throw new Error(`${dataPath} is not a regular file`)
return readFileSync(dataPath, 'utf-8')
} Type guard
function isRuntimeClientError(e: unknown): e is RuntimeClientError {
return e instanceof RuntimeClientError
} Try / catch
try {
readPersistedState(dataPath)
} catch (e) {
if (e instanceof RuntimeClientError && e.code === 'runtime_error') {
// back up and delete corrupt file so defaults regenerate
// renameSync(dataPath, dataPath + '.bak')
}
throw e
} Prevention
- Back up state files before destructive edits.
- Ensure writePersistedState's atomic temp+rename stays on the same filesystem to avoid partial writes.
- Run validation/recovery on corrupt state instead of crashing.
When it happens
Trigger: existsSync(dataPath) is true but readFileSync throws (permissions, EISDIR), or JSON.parse throws (truncated/corrupt JSON), or the parsed value is not a record (inner throw at 538).
Common situations: Corrupt or truncated state file (crash mid-write before the atomic rename), permissions changed on the file, the path points at a directory, or a partial write from a killed process.
Related errors
- file does not contain a JSON object
- Artifact share records could not be read safely.
- Failed to persist Codex session index-heal outcome for ${thr
- [plain-node-entry-guard] could not smoke-load daemon-entry.j
- Missing packaged resources directory: ${resourcesDir}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/0e785f399825c7d7.
Report an issue: GitHub.