How to Debug ID Collision Issues Using the ImGui ID Stack Tool
The ImGui ID Stack Tool visualizes every intermediate hash value that contributes to a widget's final 32-bit identifier, allowing you to trace exactly which PushID calls or string literals cause two widgets to receive the same ImGuiID and trigger collision warnings.
Dear ImGui (ocornut/imgui) generates unique 32-bit identifiers for every widget by hashing a hierarchical stack of strings, integers, and pointers. When two widgets accidentally receive the same hash, the library flags the conflict via DebugDrawIdConflictsId, but tracing the root cause requires inspecting the full ID stack. The ID Stack Tool provides this visibility, showing each step of the hash computation in a tree view.
Understanding ImGui ID Collisions
Every widget in Dear ImGui receives an ImGuiID created by hashing the current ID stack. The stack typically includes window names, PushID calls, and implicit string labels. When the hash function produces identical values for two different widgets, ImGui draws a red outline around the conflicting items and sets the internal DebugDrawIdConflictsId variable to flag the collision.
Without visibility into the intermediate hash values, resolving these conflicts is guesswork. The collision warning tells you that two widgets share an ID, but not which specific PushID calls or string literals created the duplicate.
How the ID Stack Tool Works
The tool is powered by the ImGuiIDStackTool structure defined in imgui_internal.h (lines 2214–2222), which stores inspection options including hex-encoding and clipboard handling. It operates through a hook mechanism: when you set DebugHookIdInfoId (line 2306) to a specific ID, all GetID* functions call ImGui::DebugHookIdInfo() whenever they generate a matching identifier.
This hook feeds the tool with stack-level details using ImGuiDataType_* identifiers, revealing how each PushID, PushOverrideID, or pointer contributed to the final hash. The result is a tree view where each node represents one step of the hash computation, from the root window down to the final widget ID.
Opening the ID Stack Tool
You can activate the tool through the Demo menu or programmatically.
Via the Demo Menu: Navigate to Demo > Tools > ID Stack Tool to open the inspection window.
Programmatically:
Call ImGui::ShowIDStackToolWindow() from your code to open the tool directly, which is useful when building debugging utilities:
if (ImGui::Button("Show ID Stack"))
ImGui::ShowIDStackToolWindow();
According to the implementation in imgui.cpp (around line 18367), this function creates the tool window and initializes the inspection state.
Tracing ID Collisions
When an ID collision occurs, hover over the widget displaying the red conflict outline. The ID Stack Tool automatically selects that ID and displays the full hash stack.
The tree view reveals:
- Each
PushIDcall with its associated string or integer value - Any
PushOverrideIDcalls that may have disrupted the hash sequence - Pointer values that contributed to the hash
Common Collision Patterns:
- Duplicate string literals: Reusing the same label (e.g.,
"OK") inside different parent scopes without an additionalPushIDcreates identical hashes. - Override conflicts: Calling
PushOverrideID(0)where the underlying hash would otherwise be unique. - Dynamic index collisions: Mixing static IDs like
ImGui::GetID("Button")with dynamic data (e.g., array indices that reset each frame) causing unintended hash repetitions.
Resolving Collisions
Once the tool identifies which stack level causes the duplication, wrap the conflicting widgets in unique PushID scopes:
// Problem: Both buttons share the same implicit ID
if (ImGui::Button("OK")) { /* ... */ }
ImGui::SameLine();
if (ImGui::Button("OK")) { /* ... */ } // Collision: same hash("OK")
// Solution: Add explicit PushID scopes
ImGui::PushID("DialogA");
if (ImGui::Button("OK")) { /* ... */ } // ID = hash("DialogA", "OK")
ImGui::PopID();
ImGui::PushID("DialogB");
if (ImGui::Button("OK")) { /* ... */ } // ID = hash("DialogB", "OK")
ImGui::PopID();
For manual investigation of a specific ID flagged by DebugDrawIdConflictsId, you can force the tool to inspect it directly:
ImGuiID problematic_id = g.DebugDrawIdConflictsId; // ID flagged by ImGui
ImGui::DebugHookIdInfoId = problematic_id; // Force the tool to follow this ID
Summary
- ImGui ID collisions occur when two widgets generate identical 32-bit hashes from the ID stack, triggering red outlines and setting
DebugDrawIdConflictsId. - The ID Stack Tool (defined in
imgui_internal.hlines 2214–2222) visualizes every intermediate hash step via theDebugHookIdInfohook mechanism. - Open the tool via Demo > Tools > ID Stack Tool or by calling
ImGui::ShowIDStackToolWindow()(implemented inimgui.cpparound line 18367). - Hover over colliding widgets to auto-select their ID, then examine the stack to identify duplicate
PushIDvalues or conflicting string literals. - Fix collisions by adding unique
PushIDscopes or changing the data used to generate widget identifiers.
Frequently Asked Questions
How do I know if my ImGui widgets have ID collisions?
When two active widgets share the same ImGuiID, Dear ImGui draws a red outline around the conflicting widgets and sets the internal DebugDrawIdConflictsId variable to the problematic hash value. You will see visual distortion in the UI and can check the global debug state to confirm the collision ID.
What is the ImGuiIDStackTool structure used for?
The ImGuiIDStackTool structure (defined in imgui_internal.h at lines 2214–2222) stores the internal state for the ID Stack Tool, including the currently inspected ID, display options for hex-encoding, and clipboard export settings. It powers the visualization that shows how each PushID and string literal contributes to the final widget hash.
Can I programmatically force the ID Stack Tool to inspect a specific widget?
Yes. Set the ImGui::DebugHookIdInfoId global to the target ImGuiID (for example, the value stored in DebugDrawIdConflictsId). The next time the UI generates that ID, the DebugHookIdInfo function will capture the full stack trace and display it in the tool window.
Where can I find example code for using the ID Stack Tool?
The official demo code in imgui_demo.cpp contains examples showing how to call ImGui::ShowIDStackToolWindow() and demonstrates ID conflict visualization. Additionally, the docs/FAQ.md file provides a brief user guide mentioning the tool's location in the Demo menu.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →