stablyai/orca · error · Error
codex trust-grant entry produced no result (exit ${spawned.s
Error message
codex trust-grant entry produced no result (exit ${spawned.status ?? 'unknown'})${spawned.stderr ? `: ${spawned.stderr.trim().slice(0, 400)}` : ''} What it means
Thrown by the synchronous grant-bridge after it spawnSyncs the bundled ELECTRON_RUN_AS_NODE entry child and cannot parse a JSON envelope from the last non-empty stdout line. The bridge exists because hook-trust grant is synchronous launch prep, but the actual JSON-RPC session needs a live event loop, so it runs in a short-lived node child that must print exactly one JSON envelope on stdout. A missing/unparseable envelope means the entry crashed, was killed, or wrote garbage before it could report a structured result.
Source
Thrown at src/main/codex/codex-app-server-grant-bridge.ts:128
throw spawned.error
}
if (spawned.signal) {
throw new CodexAppServerTimeoutError(
`codex trust-grant entry killed by ${spawned.signal} after ${request.invocation.timeoutMs}ms deadline`
)
}
const lines = (spawned.stdout ?? '').split('\n').filter((line) => line.trim().length > 0)
const lastLine = lines.at(-1)
let envelope: GrantEntryEnvelope | null = null
if (lastLine) {
try {
envelope = JSON.parse(lastLine) as GrantEntryEnvelope
} catch {
envelope = null
}
}
if (!envelope) {
throw new Error(
`codex trust-grant entry produced no result (exit ${spawned.status ?? 'unknown'})${
spawned.stderr ? `: ${spawned.stderr.trim().slice(0, 400)}` : ''
}`
)
}
if (!envelope.ok) {
if (envelope.unsupported) {
throw new CodexAppServerUnsupportedError(envelope.message)
}
if (envelope.errorName === 'CodexAppServerTimeoutError') {
throw new CodexAppServerTimeoutError(envelope.message)
}
throw new Error(envelope.message)
}
return envelope.result
}
View on GitHub (pinned to 1136503c6a)
Solutions
- Inspect the embedded exit status and first 400 chars of stderr in the message to classify the failure (non-zero exit vs killed vs empty stdout).
- If exit is 'unknown' or shows SIGKILL, raise request.invocation.timeoutMs or the test-only timeoutMarginMs so the entry has room to finish and report.
- If stderr shows a stack trace, reproduce by running the entry directly: ELECTRON_RUN_AS_NODE=1 node <resolveCodexGrantEntryPath()> with the request JSON on stdin.
- Verify the packaged build emits the entry under app.asar.unpacked/out/main/codex (resolveCodexGrantEntryPath replaces app.asar with app.asar.unpacked).
- If the entry prints non-JSON log lines after the envelope, ensure only buildGrantEntryEnvelope output goes to stdout and all diagnostics go to stderr.
Example fix
// before: entry mixes a console.log after the envelope
process.stdout.write(JSON.stringify(envelope) + '\n')
console.log('done') // makes the last stdout line 'done', not JSON
// after: only the envelope touches stdout
default: {
process.stderr.write('done\n')
process.stdout.write(JSON.stringify(envelope) + '\n')
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling runCodexHookTrustGrantSessionSync, verify the entry resolves:
const entryPath = resolveCodexGrantEntryPath()
if (!entryPath || !existsSync(entryPath)) {
// skip the real-home lane; stay managed
} Type guard
function isGrantEntryNoResultError(error: unknown): boolean {
return error instanceof Error && error.message.startsWith('codex trust-grant entry produced no result')
} Try / catch
try {
const result = runCodexHookTrustGrantSessionSync(request)
// use result
} catch (error) {
if (isGrantEntryNoResultError(error)) {
// inspect message for exit/stderr; fall back to managed lane, retry later
currentLane = 'unavailable'
installRetryAfterMs = Date.now() + CODEX_TRUST_GRANT_TRANSIENT_RETRY_INTERVAL_MS
} else {
throw error
}
} Prevention
- Ensure the entry bundle is emitted and asar-unpacked in production builds.
- Size invocation.timeoutMs + timeoutMarginMs to the worst-case session length.
- Route all entry diagnostics to stderr so stdout's last line is always the JSON envelope.
- Run the entry standalone during CI to catch crash-before-envelope regressions.
When it happens
Trigger: The entry child exited non-zero (or was SIGKILLed by the spawnSync timeout margin) without writing a parseable final JSON line; stdout was empty; the entry threw before reaching buildGrantEntryEnvelope; maxBuffer (16MB) was exceeded truncating the envelope; or the entry printed log noise after the envelope so the 'last line' is not JSON.
Common situations: A codex CLI upgrade changed app-server handshake behavior so the entry's session throws early; the entry bundle is missing/corrupt in a packaged build (asar.unpacked path mismatch); the system is under heavy load so the entry exceeds timeoutMs+margin and is killed; antivirus or sandbox policy strips the child's stdout on Windows.
Related errors
- codex app-server session already timed out
- codex app-server does not support ${method}: ${response.erro
- codex app-server ${method} failed: ${response.error.message
- ${envelope.message}
- codex CLI does not support the app-server subcommand: ${stde
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/48d2992c96002934.
Report an issue: GitHub.