NationalSecurityAgency/ghidra · error · LSHException
Trying to insert on read-only database
Error message
Trying to insert on read-only database
What it means
`fdbDatabaseInsert` checks `info.readonly` at entry. If the connection was opened read-only, any insert is rejected with LSHException before any work begins. Read-only mode is intended for query-only clients; writes are refused outright.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/AbstractSQLFunctionDatabase.java:1937
response.result.add(simres);
simres.transfer(response.manage, true);
}
return vecToResultMap.size();
}
/**
* Entry point for the InsertRequest command
* @param query the query to execute
* @throws LSHException if trying to insert into a read-only database
* @throws SQLException if there is an error issuing the query
* @throws DatabaseNonFatalException if there are duplicate executables and/or functions
*/
private void fdbDatabaseInsert(InsertRequest query)
throws LSHException, SQLException, DatabaseNonFatalException {
if (info.readonly) {
throw new LSHException("Trying to insert on read-only database");
}
if (FunctionDatabase.checkSettingsForInsert(query.manage, info)) { // Check if settings are valid and is this is first insert
info.major = query.manage.getMajorVersion();
info.minor = query.manage.getMinorVersion();
info.settings = query.manage.getSettings();
keyValueTable.writeBasicInfo(info); // Save off the settings associated with this first insert
}
ResponseInsert response = query.insertresponse;
if ((query.repo_override != null) && (query.repo_override.length() != 0)) {
query.manage.overrideRepository(query.repo_override, query.path_override);
}
insert(query.manage);
response.numexe = query.manage.getExecutableRecordSet().size();
response.numfunc = query.manage.numFunctions();
}
/**
* Entry point for the QueryInfo commandView on GitHub (pinned to d5f144c24d)
Solutions
- Open the connection without the read-only flag.
- Use a separate, read-write connection/client for insert operations.
- Verify the connection's readonly setting before dispatching InsertRequest.
Example fix
// before: readonly connection used for ingest info.readonly = true; db.insert(query); // throws // after: writable connection for writes info.readonly = false; db.insert(query);
Defensive patterns
Strategy: validation
Validate before calling
// Guard inserts against a read-only connection.
if (db.getInfo().readonly) {
throw new IllegalStateException(
"Cannot insert on a read-only connection; open read-write");
} Try / catch
try {
db.insert(query);
} catch (LSHException e) {
if (e.getMessage().equals("Trying to insert on read-only database")) {
// operator must use a read-write connection -- do not retry as-is
throw new ConnectionModeException("Reopen the DB read-write for inserts", e);
}
throw e;
} Prevention
- Use distinct read-only (query) and read-write (ingest) clients.
- Verify info.readonly before dispatching InsertRequest.
- Fail fast on mode mismatch rather than discovering it mid-ingest.
When it happens
Trigger: Opening a BSim DB connection in read-only mode (e.g. for similarity queries) and then dispatching an InsertRequest against it.
Common situations: Misconfigured connection URL/flags; reusing a query-only client for ingest; a DB role restricted to read; a deliberate read-only replica used accidentally for writes.
Related errors
- Id mismatch when inserting executable:
- is already ingested
- Already inserted
- Did not get desctable sequence number after insertion
- Did not get exetable sequence number after insertion
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/365bf3153cce9957.
Report an issue: GitHub.