Skip to content

Recover from a crashed IDA session instead of failing forever - #226

Open
subwire wants to merge 1 commit into
mainfrom
recover-stale-ida-database
Open

Recover from a crashed IDA session instead of failing forever#226
subwire wants to merge 1 commit into
mainfrom
recover-stale-ida-database

Conversation

@subwire

@subwire subwire commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Problem

A decompiler server that dies uncleanly leaves IDA's unpacked database components (.id0, .id1, .id2, .nam, .til) in the project directory. IDA reads those as a database that is still open and refuses to reopen it — so every subsequent load of that binary fails, permanently, for that project:

ERROR - Failed to start server: Failed to open database /tmp/t

Nothing in the message suggests the project is poisoned or how to clear it.

Reproduced deterministically:

decompiler load /tmp/t --backend ida --project-dir /tmp/proj   # ok
pkill -9 -f "declib.*--server"                                 # crash
decompiler load /tmp/t --backend ida --project-dir /tmp/proj   # Failed to open database
rm -rf /tmp/proj && decompiler load ...                        # ok again

Why it matters

We ran 40 binaries through DecLib as the sole decompiler interface and compared against an MCP-based baseline. 64 of 80 DecLib failures were this one bug. The same binary failed up to 7 times in a row, because nothing ever cleared the residue and the agent had no way to know it needed to.

It was also the biggest single driver of wasted effort. Across six challenges, agents spent 77 commands reading server logs — nearly as many as they spent on actual analysis (83) — trying to work out why loads kept failing.

The distinction that makes a safe fix possible

state contents
live session .i64 + unpacked components
clean stop --save .i64 only (IDA repacks) — reload works
unclean death .i64 + orphaned unpacked components → poisoned

So unpacked components with no live server are unambiguously crash residue, and the user's actual work is in the .i64.

Change

cmd_load clears the unpacked components before spawning — but only when no live server owns the project (the existing --replace / already-loaded checks above have already returned or torn those down), so a running session is never disturbed.

The .i64/.idb is deliberately preserved. Verified end-to-end: set a comment, save, kill -9 the server, reload — the comment is still there. Only the regenerable cache is removed.

Scoped to the IDA backend; a no-op for ghidra/angr/binja.

Tests

Five cases: removes the unpacked components; preserves the saved .i64; no-op for other backends; no-op when nothing is stale; tolerates a missing/None project dir.

🤖 Generated with Claude Code

A server that dies uncleanly leaves IDA's unpacked database components
(.id0/.id1/.id2/.nam/.til) in the project directory. IDA reads those as a
database that is still open and refuses to reopen it, so **every**
subsequent load of that binary fails with "Failed to open database" --
permanently, for that project, with nothing in the message to suggest a
remedy.

Reproduced deterministically: load a binary, `kill -9` the server, load
again -> failure. Wipe the project dir -> works. The same binary failed up
to 7 times in a row during a benchmark because nothing ever cleared it.

Measured on a 40-binary run: **64 of 80** DecLib failures were this. It was
also the single largest driver of wasted agent effort -- 77 commands spent
reading server logs across six challenges, nearly as many as were spent on
analysis, because the error gives no hint that the project is poisoned.

cmd_load now clears the unpacked components before spawning, but only when
no live server owns the project (the existing checks above have already
returned or torn those down), so this cannot disturb a running session.

The saved .i64/.idb is deliberately preserved: that is where annotations
live. Verified end-to-end -- comment, save, `kill -9`, reload, and the
comment is still there. Only the unpacked cache is removed, and reanalysis
regenerates it.

Scoped to the IDA backend; a no-op for ghidra/angr/binja.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant