{"record":{"id":"62d6c9df7d62a25c","repo":"NationalSecurityAgency/ghidra","slug":"unknown-vector-hash","errorCode":null,"errorMessage":"Unknown vector hash","messagePattern":"Unknown vector hash","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/H2VectorTable.java","lineNumber":231,"sourceCode":"\t\ts.setInt(1, countDiff);\n\t\ts.setLong(2, vecHash);\n\t\tint rc = s.executeUpdate();\n\t\tif (rc == 0) {\n\t\t\treturn insert(countDiff, vec);\n\t\t}\n\t\tif (rc > 1) {\n\t\t\tthrow new SQLException(\"Unexpected updated row count: \" + rc);\n\t\t}\n\n\t\ts = select_id_by_hash_stmt.prepareIfNeeded(() -> db\n\t\t\t\t.prepareStatement(\"SELECT id, count FROM \" + TABLE_NAME + \" WHERE vec_hash = ?\"));\n\t\ts.setLong(1, vecHash);\n\n\t\tlong id;\n\t\tint count;\n\t\ttry (ResultSet rs = s.executeQuery()) {\n\t\t\tif (!rs.next()) {\n\t\t\t\tthrow new SQLException(\"Unknown vector hash\");\n\t\t\t}\n\t\t\tid = rs.getLong(1);\n\t\t\tcount = rs.getInt(2);\n\t\t}\n\t\tvectorStore.update(\n\t\t\tnew VectorStoreEntry(id, vec, count, vectorFactory.getSelfSignificance(vec)));\n\t\treturn id;\n\t}\n\n\t/**\n\t * Update vector table entry with the specified countDiff.  Record will be removed\n\t * if reduced vector count less-than-or-equal zero. \n\t * @param id vector ID\n\t * @param countDiff positive vector count reduction\n\t * @return 0 if decrement short of 0, return 1 if record was removed, return\n\t *         -1 if there was a problem\n\t * @throws SQLException if an error occurs\n\t */","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/H2VectorTable.java#L213-L249","documentation":"Thrown inside H2VectorTable.updateVector() after a successful UPDATE (rc==1) on the vec_hash, but the subsequent SELECT id,count by that same vec_hash returns zero rows. The hash was just written but is no longer found, indicating a data-consistency violation in the H2 vector table between the UPDATE at line 215 and the SELECT at line 229.","triggerScenarios":"Concurrent modification of H2VectorTable between the UPDATE (line 210-215) and the SELECT (line 223-234): another thread or transaction deletes the row. Alternatively, vec.calcUniqueHash() returns inconsistent values across calls due to a vector factory version mismatch or corrupted vector data.","commonSituations":"Running multi-threaded BSim ingest against a shared H2 file database without proper transaction isolation; migrating a BSim database between Ghidra versions where the hash algorithm changed; database file corruption after an unclean shutdown.","solutions":["Ensure single-writer access to the H2 database file during ingest (BSim H2 file DBs are not designed for concurrent writes).","Verify the BSim database was created with the same Ghidra version and vector factory configuration as the code reading it.","Run a database consistency check or rebuild the index using the 'rebuildindex' BSim command.","If the database is corrupted, recreate it using 'createdatabase' and re-ingest signatures."],"exampleFix":"// before: concurrent updates from multiple threads can interleave\nExecutorService pool = Executors.newFixedThreadPool(4);\nfor (var vec : vectors) {\n    pool.submit(() -> table.updateVector(vec, 1));\n}\n\n// after: serialize writes to avoid interleaved UPDATE/SELECT\nfor (var vec : vectors) {\n    table.updateVector(vec, 1); // single-threaded, or use a connection-per-thread model","handlingStrategy":"try-catch","validationCode":"// Ensure single-writer access before calling updateVector\nif (!isSingleWriter(db.getConnection())) {\n    throw new IllegalStateException(\"Concurrent write detected on BSim H2 database\");\n}\ntable.updateVector(vec, countDiff);","typeGuard":null,"tryCatchPattern":"try {\n    long id = table.updateVector(vec, countDiff);\n} catch (SQLException e) {\n    if (e.getMessage().contains(\"Unknown vector hash\")) {\n        // Row vanished between UPDATE and SELECT — likely concurrency or hash mismatch\n        // Retry once under a fresh transaction, or fall back to insert\n        table.insert(countDiff, vec);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Ensure only one thread writes to the H2 database file at a time.","Use H2 database-level locking (e.g., AUTO_SERVER=FALSE, file_lock=fs) to prevent multi-process access.","Verify vector factory configuration matches the database's hash algorithm before ingesting."],"tags":["bsim","ghidra","database","h2","data-integrity","concurrency"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}