# How to Debug Layout Issues and Resolve Widget ID Conflicts in Dear ImGui

> Debug Dear ImGui layout problems and widget ID conflicts. Learn to use debug overlays like ShowMetricsWindow and tools like PushID PopID for efficient issue resolution.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Dear ImGui uses a stack-based ID system where widget identifiers are hashed from the current ID stack plus the widget label, and layout issues can be diagnosed using built-in debug overlays like `ShowMetricsWindow` and `ShowIDStackToolWindow` while ID conflicts are resolved using `PushID`/`PopID` or explicit ID suffixes.**

When building sophisticated user interfaces with the `ocornut/imgui` repository, layout misalignments and state-sharing bugs between unrelated widgets are common pitfalls. These issues typically stem from Dear ImGui's internal ID generation mechanism and the implicit stack that tracks hierarchical context. Understanding how to leverage the library's built-in debugging utilities allows you to quickly identify clipping problems, positioning errors, and duplicate ID collisions.

## Understanding the ID Stack Architecture in Dear ImGui

Every widget in Dear ImGui receives a unique `ImGuiID` generated by hashing the current **ID stack** state combined with the widget's label or pointer identifier. In [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (line 610), the `GetID` overloads—`ImGui::GetID(const char* str_id)`, `GetID(void* ptr_id)`, and `GetID(int int_id)`—compute this hash by mixing the supplied value with the active stack context stored in `ImGuiContext`.

The core implementation resides in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) (line 2829), where internal functions `GetID`, `GetIDFromPos`, and `GetIDFromRectangle` serve as the workhorses feeding into all widget APIs. When you call a widget function like `Button("OK")`, Dear ImGui internally executes:

```cpp
ImGuiID id = GetID("##OK");          // hash of current stack + "##OK"
ItemAdd(rect, id);

```

If the same stack state and label appear elsewhere in your code, the resulting hash becomes identical, triggering an **ID conflict** where Dear ImGui shares state (active, hovered, focused) between unrelated widgets.

## Detecting and Debugging Layout Issues in Dear ImGui

Layout problems manifest as misplaced, clipped, or overlapping widgets, often caused by incorrect cursor positioning or parent window constraints. Dear ImGui provides several diagnostic tools to visualize these issues in real-time.

### Visual Debug Overlays

The following helper functions, declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), draw immediate visual feedback over your interface:

- **`DebugDrawItemRect`** - Outlines the last item's bounding rectangle in a specified color (defaults to red)
- **`DebugDrawCursorPos`** - Displays the current cursor (pen) position used for layout calculations
- **`ShowDebugLogWindow`** - Prints diagnostic messages including ID-generation logs
- **`ShowMetricsWindow`** - Exposes full internal state including windows, draw lists, and active IDs

To use these utilities, ensure `IMGUI_DISABLE_DEBUG_TOOLS` is **not** defined in [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) (line 38). A typical debugging workflow looks like:

```cpp
if (ImGui::BeginMenuBar())
{
    if (ImGui::MenuItem("Debug##Layout"))
        ImGui::ShowMetricsWindow();   // toggles the debug window
    ImGui::EndMenuBar();
}

// Inside a problematic window:
ImGui::DebugDrawItemRect();           // draws a red outline around the last item
ImGui::DebugDrawCursorPos();          // shows where the next widget will be placed

```

These overlays let you compare the expected rectangle (`GetItemRectMin`/`GetItemRectMax`) with the actual rendered area, revealing misaligned calls to `SetNextWindowPos`, `SetNextItemWidth`, or unexpected `BeginGroup`/`EndGroup` nesting.

### Programmatic Layout Queries

For precise debugging, query the layout state directly:

```cpp
ImVec2 min = ImGui::GetItemRectMin();   // top-left of the last item
ImVec2 max = ImGui::GetItemRectMax();   // bottom-right of the last item
ImGuiID id  = ImGui::GetItemID();        // ID of the last item

```

If a widget appears collapsed or invisible, the rectangle may be zero-sized, indicating a missing `SetNextItemWidth` or a parent window that clipped it.

## Resolving Widget ID Conflicts in Dear ImGui

When Dear ImGui detects two active items with the same `ImGuiID`, it increments `DebugDrawIdConflictsCount` (defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) line 2611) and highlights the overlapping IDs in the **ID Stack Tool**. Conflicts typically occur when labels are reused without unique prefixes in loops, when separate windows share identical implicit ID stacks, or when `PushID`/`PopID` misuse leaves the stack in an unexpected state.

### Using the ID Stack Tool

The **ID Stack Tool** is your primary diagnostic for ID collisions. You can open it by pressing **Ctrl+Alt+I** (default) or calling `ImGui::ShowIDStackToolWindow()`. When active, hover over any widget to see the full stack trace of each `PushID` and `Begin` entry that contributed to that widget's ID.

The underlying data lives in `ImGuiContext::DebugIDStackTool` ([`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) line 2628). When a conflict is detected, `DebugDrawIdConflictsId` is set, causing the overlay to flash conflicting IDs in the Metrics window. The internal function `DebugHookIdInfo` (line 3846 in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h)) is invoked from every `GetID` call when debug tools are active, allowing the stack overlay to show the complete generation path.

### Best Practices for Unique IDs

Implement these patterns to prevent collisions:

**Explicit ID suffixes** - Append `##` followed by a unique token to the label:

```cpp
ImGui::Button("Save##File1");
ImGui::Button("Save##File2");  // Different ID despite same display text

```

**PushID/PopID** - Surround repeated sections with stack pushes:

```cpp
for (int i = 0; i < num_entries; ++i)
{
    ImGui::PushID(i);                 // guarantees a unique stack element
    if (ImGui::Button("Delete"))
        DeleteEntry(i);
    ImGui::PopID();
}

```

**GetIDWithSeed** - Generate deterministic IDs with custom seeds when you need specific hash control:

```cpp
ImGuiID id = ImGui::GetIDWithSeed("Item", mySeed);

```

If you cannot modify labels (e.g., third-party code), wrap regions with a unique `PushID` using a pointer or hash of the enclosing context.

## Practical Debugging Examples

### Debugging a Misaligned Window

```cpp
// Toggle the metrics/debug windows
if (ImGui::Button("Show Debug")) ImGui::ShowMetricsWindow();

// Inside the window you suspect
ImGui::Text("Current cursor: (%.1f, %.1f)", 
            ImGui::GetCursorScreenPos().x,
            ImGui::GetCursorScreenPos().y);
ImGui::DebugDrawCursorPos();      // red dot at the cursor
ImGui::DebugDrawItemRect();       // red outline around the last widget

```

Running the above reveals if the cursor moved unexpectedly—such as after an extra `SameLine()` or missing `SetNextWindowPos`—by showing exactly where Dear ImGui thinks the next item should render.

### Fixing Duplicate IDs in a List

```cpp
for (int row = 0; row < rows; ++row)
{
    ImGui::PushID(row);                 // unique stack per row
    ImGui::Text("Row %d", row);
    ImGui::SameLine();
    if (ImGui::Button("Edit")) { /* … */ }
    ImGui::SameLine();
    if (ImGui::Button("Delete")) { /* … */ }
    ImGui::PopID();
}

```

Without `PushID`/`PopID`, the two `Button("Edit")` calls across rows share the same ID, causing the *Edit* button of the previously drawn row to activate when you click the current one.

### Logging ID Conflicts Manually

```cpp
void MyWidget()
{
    ImGuiID id = ImGui::GetID("MyWidget");
    if (ImGui::DebugDrawIdConflictsCount > 0)
        ImGui::LogWarning("ID conflict detected for %s!", "MyWidget");
    // Normal widget code…
}

```

Warnings appear in the **Debug Log** window opened via `ImGui::ShowDebugLogWindow()`.

## Summary

- Dear ImGui generates widget IDs by hashing the current **ID stack** with the widget label or pointer, making stack management critical for avoiding conflicts.
- Layout issues can be diagnosed using **`DebugDrawItemRect`** and **`DebugDrawCursorPos`** to visualize bounding boxes and cursor positions, or by opening **`ShowMetricsWindow`** for comprehensive state inspection.
- ID conflicts are resolved by using **`PushID`**/`**PopID**` to create unique stack contexts, appending **`##unique_suffix`** to labels, or utilizing **`GetIDWithSeed`** for deterministic hashing.
- The **ID Stack Tool** (activated with Ctrl+Alt+I or **`ShowIDStackToolWindow`**) displays the complete ID generation path for hovered widgets, making collision sources immediately visible.
- Ensure **`IMGUI_DISABLE_DEBUG_TOOLS`** is not defined in [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) (line 38) to access the full debugging toolkit available in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h).

## Frequently Asked Questions

### What causes widget ID conflicts in Dear ImGui?

Widget ID conflicts occur when two widgets generate the same `ImGuiID` hash value, typically because they share identical labels within the same ID stack scope, such as buttons created inside a loop without unique identifiers. According to the `ocornut/imgui` source code in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) (line 2611), when Dear ImGui detects these collisions, it increments `DebugDrawIdConflictsCount` and can highlight the conflicting items in the ID Stack Tool.

### How do I visualize widget bounding boxes for layout debugging?

Use **`ImGui::DebugDrawItemRect()`** immediately after the widget you want to inspect to draw a colored outline around its calculated rectangle, or call **`ImGui::DebugDrawCursorPos()`** to see the exact screen coordinates where Dear ImGui will place the next item. For comprehensive diagnostics, open **`ImGui::ShowMetricsWindow()`** to inspect window boundaries, draw lists, and item rectangles simultaneously.

### What is the purpose of PushID and PopID in Dear ImGui?

**`PushID`** and **`PopID`** manipulate the internal ID stack to create unique namespaces for widgets, ensuring that identical labels in different contexts (such as buttons inside a loop or across multiple child windows) generate distinct `ImGuiID` hashes. As implemented in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (line 610), these functions prepend a unique value to the stack before `GetID` calculates the final hash, preventing state collisions between separate UI elements.

### How do I enable debug tools if they are missing from my build?

Verify that **`IMGUI_DISABLE_DEBUG_TOOLS`** is not defined in your [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) file (line 38), as this preprocessor directive strips out all debugging utilities including `ShowMetricsWindow` and the ID Stack Tool. Once enabled, the debug functions declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) become available for diagnosing both layout issues and ID conflicts at runtime.