NationalSecurityAgency/ghidra · error · SQLException
Bad vectable rowid
Error message
Bad vectable rowid
What it means
Thrown by PostgresFunctionDatabase.queryVectorId() when a SELECT by the given row id returns no rows from the vectable. This means no vector record exists with the requested id — the id is stale, was already deleted, or never existed.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/PostgresFunctionDatabase.java:539
}
SimilarityVectorResult simres = new SimilarityVectorResult(frec);
simres.addNotes(resultset);
response.totalmatch += simres.getTotalCount();
if (simres.getTotalCount() == 1) {
response.uniquematch += 1;
}
response.result.add(simres);
}
}
@Override
protected VectorResult queryVectorId(long id) throws SQLException {
PreparedStatement s = selectVectorByRowIdStatement.prepareIfNeeded(() -> initConnection()
.prepareStatement("SELECT id,count,vec FROM vectable WHERE id = ?"));
s.setLong(1, id);
try (ResultSet rs = s.executeQuery()) {
if (!rs.next()) {
throw new SQLException("Bad vectable rowid");
}
VectorResult rowres;
try {
rowres = new VectorResult();
rowres.vectorid = rs.getLong(1);
rowres.hitcount = rs.getInt(2);
rowres.vec = vectorFactory.restoreVectorFromSql(rs.getString(3));
}
catch (final IOException e) {
throw new SQLException(e.getMessage());
}
return rowres;
}
}
@OverrideView on GitHub (pinned to d5f144c24d)
Solutions
- Verify the vector id is valid and the corresponding vectable row still exists before querying.
- If the row may have been deleted, handle the missing-row case gracefully in the caller.
- Ensure no concurrent process is deleting vectors that this query depends on.
Example fix
// before
VectorResult vr = db.queryVectorId(id); // throws "Bad vectable rowid" if deleted
// after — guard against stale id
// (check existence first, or catch SQLException)
try {
VectorResult vr = db.queryVectorId(id);
} catch (SQLException e) {
if (e.getMessage().contains("Bad vectable rowid")) {
// vector was deleted; handle gracefully
} else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the vector id still exists before querying // (requires a separate existence check or tracking deletion state) // If you have access to a connection: // SELECT 1 FROM vectable WHERE id = ?
Try / catch
try {
VectorResult vr = db.queryVectorId(id);
} catch (SQLException e) {
if (e.getMessage().equals("Bad vectable rowid")) {
// vector was deleted or id is invalid; handle gracefully
return null;
}
throw e;
} Prevention
- Track which vector ids have been deleted to avoid stale lookups.
- Validate that an id is non-zero and within expected range before querying.
- Handle missing-vector gracefully if concurrent deletions are possible.
When it happens
Trigger: Calling queryVectorId(id) with an id that does not correspond to any row in vectable. This occurs when a previously obtained vector id references a row that was subsequently removed (e.g. by deleteVectors reducing count to zero), or when an invalid/zero id is passed.
Common situations: A SignatureRecord's vector id was deleted by a concurrent or prior operation. A reference to a vector id was persisted and the underlying row was cleaned up. An off-by-one or uninitialized id (e.g. 0 or -1) is passed accidentally.
Related errors
- Could not create database:
- database in use
- attempted to drop non-BSim database
- Did not get vector id after insertion
- Did not get result code after deletion
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/63d720bc889838e4.
Report an issue: GitHub.