NationalSecurityAgency/ghidra · error · SQLException

ExecutableRecord does not have id

Error message

ExecutableRecord does not have id

What it means

Thrown by ExeToCategoryTable.queryExecutableCategories when the exeid parameter is 0, which the code treats as 'no id'. An ExecutableRecord with a zero/null-equivalent id has not been persisted to the database, so querying its categories is invalid. Category lookups require a real exetable row id.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/tables/ExeToCategoryTable.java:141

			String type = catstringtable.getString(row.id_type);
			String category = catstringtable.getString(row.id_category);
			CategoryRecord catrec = new CategoryRecord(type, category);
			vecres.add(catrec);
		}
	}

	/**
	 * 
	 * @param exeid the executable table id
	 * @param max the max number of records to return
	 * @return the list of category records
	 * @throws SQLException if there is a problem creating or executing the query
	 */
	public List<CategoryRecord> queryExecutableCategories(long exeid, int max)
		throws SQLException {

		if (exeid == 0) {
			throw new SQLException("ExecutableRecord does not have id");
		}

		PreparedStatement s =
			selectCategoriesStatement.prepareIfNeeded(() -> db.prepareStatement(SELECT_STMT));
		s.setInt(1, (int) exeid);
		try (ResultSet rs = s.executeQuery()) {
			List<CategoryRecord> catvec = new ArrayList<CategoryRecord>();
			extractCategoryRecords(rs, catvec, max);
			return catvec;
		}
	}

	/**
	 * 
	 * @param erec the executable record
	 * @throws SQLException if there is a problem inserting the category 
	 */
	public void storeExecutableCategories(ExecutableRecord erec) throws SQLException {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure the ExecutableRecord has been inserted and assigned a non-zero row id before querying categories.
  2. Validate exeid != 0 upstream and throw a clearer error or skip.
  3. After insert, confirm the returned/generated id is set on the record object.
  4. Trace the insert path to verify id assignment (related to errors 811/807).

Example fix

// before
List<CategoryRecord> cats = table.queryExecutableCategories(exeRec.getRowId(), max); // id==0

// after
long exeid = exeRec.getRowId();
if (exeid == 0) {
    throw new IllegalStateException("ExecutableRecord not persisted; row id is 0");
}
List<CategoryRecord> cats = table.queryExecutableCategories(exeid, max);
Defensive patterns

Strategy: validation

Validate before calling

// Validate the executable id is set before category lookup.
long exeid = exeRec.getRowId();
if (exeid == 0) {
    throw new IllegalStateException("ExecutableRecord not persisted (id==0)");
}
return table.queryExecutableCategories(exeid, max);

Prevention

When it happens

Trigger: Calling queryExecutableCategories(0, max) — passing an exeid of 0. Happens when an ExecutableRecord's row id was never assigned (still 0/unset) and the caller forwards it directly. The guard uses 0 (not null) because the parameter is a primitive long.

Common situations: Using a freshly constructed ExecutableRecord that has not been inserted (id defaults to 0). Forgetting to persist the executable before querying its categories. Reading an id field that was never populated after insert (insert path failed to set it).

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/82708487459877a8. Report an issue: GitHub.