NationalSecurityAgency/ghidra · warning · DatabaseNonFatalException
Already inserted
Error message
Already inserted
What it means
After executable deduplication, if `pickout_storedfuncs` is set and `markPreviouslyStoredFunctions` returns false, the method throws DatabaseNonFatalException("Already inserted"). A false return means every function in the batch was already present -- nothing new remains to insert.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/AbstractSQLFunctionDatabase.java:1079
}
}
else {
input.setExeRowId(erec, tmp.getRowId());
}
input.setExeAlreadyStored(erec);
// Just because we've seen a library before doesn't mean we should stop function insertion
// Libraries are likely to be partially inserted multiple times
if (!erec.isLibrary()) {
throw new DatabaseNonFatalException(
erec.getNameExec() + " is already ingested");
}
pickout_storedfuncs = true; // At least one executable has previously inserted functions
}
}
if (pickout_storedfuncs) {
if (!markPreviouslyStoredFunctions(input, input.listAllFunctions())) {
throw new DatabaseNonFatalException("Already inserted");
}
}
}
/**
* Do the final work of inserting new ExecutableRecords into the database. This function
* assumes testExecutableDuplication has already run and marked previously ingested records
*
* @param input the executable descriptor
* @throws SQLException if database records cannot be inserted
*/
private void commitExecutables(DescriptionManager input) throws SQLException {
Iterator<ExecutableRecord> iter = input.getExecutableRecordSet().iterator();
while (iter.hasNext()) {
ExecutableRecord erec = iter.next();
if (erec.isAlreadyStored()) {
continue;
}View on GitHub (pinned to d5f144c24d)
Solutions
- Treat DatabaseNonFatalException("Already inserted") as expected and skip the batch.
- Track ingested-function inventory to avoid submitting fully-duplicate batches.
- Design ingest as idempotent and tolerant of this non-fatal result.
Example fix
// before: batch insert repeatedly throws non-fatal, aborting the run
// after: catch at the batch boundary and continue
try { db.insert(manager); }
catch (DatabaseNonFatalException e) {
log.info("batch already inserted: {}", e.getMessage());
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before insert, check whether all functions in the batch are already stored.
boolean anyNew = false;
for (FunctionDescription fd : manager.listAllFunctions()) {
if (!isAlreadyStored(fd)) { anyNew = true; break; }
}
if (!anyNew) log.info("batch fully already-inserted; skipping"); Try / catch
try {
db.insert(manager);
} catch (DatabaseNonFatalException e) {
if ("Already inserted".equals(e.getMessage())) {
// entire batch was present -- expected for re-runs, continue
log.info("batch already inserted: {}", e.getMessage());
return;
}
throw e;
} Prevention
- Maintain an ingested-function inventory to skip fully-duplicate batches.
- Design ingest as idempotent and tolerant of the non-fatal 'Already inserted'.
- Deduplicate batches before submission.
When it happens
Trigger: Inserting a batch of functions whose signatures are all already stored (prior ingest of the same executable's functions). `markPreviouslyStoredFunctions` found zero new functions and returned false.
Common situations: Re-running the same ingest; functions inserted earlier under a library context that overlaps the current set; idempotent retries.
Related errors
- is already ingested
- Could not resolve filter specifying function: [
- Id mismatch when inserting executable:
- Trying to insert on read-only database
- Could not find function: {entry.funcName}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/05527505bfaa0b84.
Report an issue: GitHub.