NationalSecurityAgency/ghidra · error · SQLException

FunctionDescription does not have id

Error message

FunctionDescription does not have id

What it means

Thrown by CallgraphTable.queryCallgraphRows when func.getId() returns null — the FunctionDescription object has not been assigned a database row id. The callgraph table is keyed by function id, so a null id makes the query impossible. This usually means the function was constructed in-memory and never inserted/queried from the database, or its id was never set after insertion.

Source

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

	}

	/**
	 * 
	 * @param func the function description
	 * @param trackcallgraph true if the database tracks call graph information
	 * @return the list of {@link CallgraphRow}s
	 * @throws SQLException if there is a problem parsing the {@link ResultSet} objects
	 */
	public List<CallgraphRow> queryCallgraphRows(FunctionDescription func,
		boolean trackcallgraph) throws SQLException {
		if (!trackcallgraph) {
			throw new SQLException("SQL database does not have callgraph information enabled");
		}
		PreparedStatement s =
			selectStatement.prepareIfNeeded(() -> db.prepareStatement(SELECT_STMT));
		RowKey funcid = func.getId();
		if (funcid == null) {
			throw new SQLException("FunctionDescription does not have id");
		}
		s.setLong(1, funcid.getLong());
		try (ResultSet rs = s.executeQuery()) {
			List<CallgraphRow> callvec = new ArrayList<>();
			while (rs.next()) {
				CallgraphRow row = extractCallgraphRow(rs);
				if (row.dest == 0) {
					continue;
				}
				callvec.add(row);
			}
			return callvec;
		}
	}

	@Override
	public long insert(Object... arguments) throws SQLException {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure the FunctionDescription has been inserted into (or queried from) the database so its row id is set before calling callgraph queries.
  2. Add a null check on func.getId() before invoking and throw a clearer upstream error or skip.
  3. Resolve the function by name/exe via DescriptionTable.querySingleDescriptionId to obtain a db-backed object with an id.
  4. Verify the insertion path returns and assigns the generated id (see error 807).

Example fix

// before
List<CallgraphRow> rows = callgraphTable.queryCallgraphRows(func, true); // func.getId()==null

// after
RowKey id = func.getId();
if (id == null) {
    throw new IllegalStateException("Function must be persisted before callgraph query: " + func.getFunctionName());
}
List<CallgraphRow> rows = callgraphTable.queryCallgraphRows(func, true);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the FunctionDescription has a row id before callgraph queries.
RowKey id = func.getId();
if (id == null) {
    throw new IllegalStateException(
        "FunctionDescription not persisted (null id): " + func.getFunctionName());
}
return callgraphTable.queryCallgraphRows(func, true);

Type guard

// Narrows a FunctionDescription to one guaranteed persisted.
public static FunctionDescription requirePersisted(FunctionDescription f) {
    if (f.getId() == null) {
        throw new IllegalStateException("FunctionDescription has no row id: " + f.getFunctionName());
    }
    return f;
}

Prevention

When it happens

Trigger: Passing a FunctionDescription to queryCallgraphRows that was created via DescriptionManager but never persisted (no row id assigned). Or a function object whose id field was not populated after an insert because the generated-keys step was skipped. Any callgraph query on an un-inserted function.

Common situations: Building FunctionDescription objects locally for matching without first resolving them against the database. Performing an insert but using the pre-insert object reference whose id is still null. Mixing in-memory and database-backed function objects and querying callgraph on the wrong kind.

Related errors


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