{"record":{"id":"eca015c3a5044ca9","repo":"NationalSecurityAgency/ghidra","slug":"could-not-delete-executable-record","errorCode":null,"errorMessage":"Could not delete executable record","messagePattern":"Could not delete executable record","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/tables/ExeTable.java","lineNumber":137,"sourceCode":"\t\tselectByNameStatement.close();\n\t\tsuper.close();\n\t}\n\n\t@Override\n\tpublic void create(Statement st) throws SQLException {\n\t\tst.executeUpdate(CREATE_STMT);\n\t}\n\n\t@Override\n\tpublic void drop(Statement st) throws SQLException {\n\t\tthrow new UnsupportedOperationException(\"ExeTable may not be dropped\");\n\t}\n\n\t@Override\n\tpublic int delete(long id) throws SQLException {\n\t\tint rowcount = super.delete(id);\n\t\tif (rowcount == 0) {\n\t\t\tthrow new SQLException(\"Could not delete executable record\");\n\t\t}\n\t\tif (rowcount > 1) {\n\t\t\tthrow new SQLException(\"Problem deleting executable record\");\n\t\t}\n\t\treturn rowcount;\n\t}\n\n\t/**\n\t * Pulls information out of the given {@link ExecutableRow} object into the given\n\t * {@link ResultSet}\n\t * \n\t * @param pgres the result set\n\t * @param res the executable row\n\t * @throws SQLException if there is a problem parsing the result set\n\t */\n\tprotected static void extractExecutableRow(ResultSet pgres, ExecutableRow res)\n\t\tthrows SQLException {\n\t\tres.rowid = pgres.getInt(1);","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/tables/ExeTable.java#L119-L155","documentation":"Thrown by ExeTable.delete when super.delete(id) returns a row count of 0, meaning no executable row matched the given id for deletion. The id does not correspond to any existing exetable row, so the delete was a no-op. This guards against silently succeeding when the caller expects a record to have been removed.","triggerScenarios":"Calling ExeTable.delete(id) with an id that does not exist in exetable. The executable was already deleted, the id is from another database, or the row never existed. Also possible if the delete WHERE clause did not match due to type mismatch (the id is cast to int).","commonSituations":"Attempting to delete an executable that was already removed (double delete). Using an id resolved from a stale or different database session. Referential cleanup scripts that assume ids still exist. Race where another process deletes the row first.","solutions":["Check that the executable id exists (querySingleExecutableId) before deleting, or treat a 0-row delete as already-gone rather than an error.","Confirm the id originated from the same database you are deleting from.","Guard against double-deletes by tracking which ids have been removed.","If the id type is mismatched (long vs int), verify the column type matches the setInt cast used internally."],"exampleFix":"// before\ntable.delete(exeId); // throws if id absent\n\n// after\ntry {\n    table.delete(exeId);\n} catch (SQLException e) {\n    if (e.getMessage().contains(\"Could not delete\")) {\n        // already absent; treat as success for idempotent cleanup\n        log.fine(\"Executable already removed: \" + exeId);\n    } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Check existence before deleting to make double-deletes explicit.\nif (exeTable.querySingleExecutableId(id) == null) {\n    log.fine(\"Executable already absent: \" + id);\n    return; // treat as success\n}","typeGuard":null,"tryCatchPattern":"try {\n    exeTable.delete(id);\n} catch (SQLException e) {\n    if (e.getMessage().contains(\"Could not delete\")) {\n        // idempotent: already gone\n        log.fine(\"Executable already removed: \" + id);\n    } else throw e;\n}","preventionTips":["Track deleted ids to avoid redundant delete calls.","Treat a 0-row delete as success for idempotent cleanup scripts.","Confirm ids originate from the same database."],"tags":["bsim","database","delete","missing-row","sql-exception"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}