Article illustration 1

The Mirage of a Successful Build

A colleague’s CodeQL database for a specific version of the monad project appeared flawless: the build finished, no compiler diagnostics surfaced, and the database file was created. Yet, any query that should have returned results—such as a simple location‑based search—returned nothing. The database existed, but it was empty.

Digging Into the Build Tracer Log

The first clue is the build tracer log, located at $DB/log/build-tracer.log. In this case the log contained a flood of catastrophic errors:

[T 00:45:26 93] CodeQL CLI version 2.23.2
[T 00:45:26 93] Initializing tracer.
…
64 errors and 1 catastrophic error detected in the compilation of "/app/monad/category/execution/ethereum/core/transaction.cpp".

A catastrophic error means the extractor could not pull any information from that compilation unit, which explains the empty query results.

Uncovering the Assertion Failure

Scrolling further back revealed the root cause:

error: assertion failed at: "decls.c", line 18401 in add_src_seq_end_of_variable_if_needed

This is an internal assertion in the CodeQL C/C++ extractor, triggered while processing a source file. The extractor’s own front‑end (based on EDG) was at fault, not the downstream compiler.

Isolating the Problematic Source

The build tracer log also listed the compilation command that led to the failure. By grepping for the assertion message and inspecting the preceding command, the offending file was identified as a snippet from the standard library header alloc_traits.h.

Copying that snippet into a temporary file (minimal.cpp) and running a small test script confirmed that the error reproduced.

Creating an Interestingness Test for cvise

To hand the CodeQL team a minimal reproducible case, a test script was written:

#!/bin/bash
set -e
cleanup() { rm -rf "$mytmpdir"; }
trap cleanup EXIT
mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
codeql database create "$mytmpdir" --language=cpp \
  --command="/usr/lib/llvm-19/bin/clang -std=gnu++23 -c minimal.cpp" \
  --overwrite
cat "$mytmpdir/log/build-tracer.log" | grep 'error: assertion failed at: "decls.c", line 18401'
status=$?
exit $status

If the assertion appears, the script exits with 0; otherwise it exits non‑zero.

Using cvise to Reduce the Test Case

With the test script in place, cvise was invoked:

cvise --n 8 test.sh minimal.cpp

cvise iteratively removes functions, statements, and template parameters, each time running the test script to ensure the bug persists. The process can last from minutes to hours, but the payoff is a tiny, human‑readable reproducer.

The final minimal.cpp looked like this:

struct __allocator_traits_base {
  template < typename >
  static constexpr int __can_construct_at{
# 1
  };
};

Despite its brevity, it still triggered the same assertion failure.

Reporting the Bug

A comprehensive bug report was assembled:

Field Value
Description CodeQL C/C++ extractor crashes with assertion failure on this code
CodeQL version 2.23.2
Minimal reproducer minimal.cpp (shown above)
Command to reproduce codeql database create /tmp/db --language=cpp --command="clang -std=gnu++23 -c minimal.cpp"
Expected behavior Successful extraction
Actual behavior error: assertion failed at: "decls.c", line 18401

With these details, the CodeQL team could quickly reproduce, debug, and patch the issue.

The Fix and Takeaway

The bug was resolved in CodeQL CLI 2.23.5, just nine days after the report. The lesson for developers is clear:

  1. Never trust a silent “success” – always inspect the build tracer log.
  2. Look for catastrophic errors – they indicate extraction failures.
  3. Isolate the failing file and create a minimal reproducer.
  4. Use cvise to shrink the test case.
  5. Report with context – include logs, commands, and expectations.

By following this workflow, a frustrating debugging session becomes a constructive contribution to the tooling ecosystem.

Source: https://intrigus.org/research/2025/11/28/what-to-do-when-codeql-database-creation-fails/