# Debug Issue

> Systematic Godot debugging decision trees for physics, signals, rendering, navigation, and input issues

- Skill: `n24q02m/debug-issue` (Agent Skill)
- Install (CLI): `npx skillmds@latest add n24q02m/debug-issue`
- Raw SKILL.md: https://api.skillmd.com/api/skills/n24q02m/debug-issue/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: n24q02m (https://skillmd.com/u/n24q02m)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/n24q02m/debug-issue

---


# Debug Issue

Systematic debugging using domain-specific decision trees. Start by identifying the symptom category, then follow the corresponding tree.

## Category Detection

Map user's symptom to the right tree:

| Symptom keywords | Category |
|---|---|
| "pass through", "no collision", "overlap", "stuck", "slides off" | Physics |
| "signal not firing", "not connected", "callback not called" | Signals |
| "invisible", "not showing", "behind", "flickering", "wrong color" | Rendering |
| "not moving to target", "path wrong", "stuck on nav", "no path" | Navigation |
| "key not working", "input ignored", "wrong button", "double input" | Input |

## Physics Decision Tree

Check in this order -- each step is the most common cause at that point:

1. **Collision layer/mask mismatch** (most common):
   - Check defined layer names: `physics(action="layers")`
   - Check node properties:
     ```
     nodes(action="get_property", scene_path="<scene>.tscn", name="<body>", property="collision_layer")
     nodes(action="get_property", scene_path="<scene>.tscn", name="<body>", property="collision_mask")
     ```
   - Rule: Object A detects Object B only if A's `collision_mask` has a bit that matches B's `collision_layer`. Both must be set correctly.

2. **Missing CollisionShape2D/3D**:
   - Inspect the scene tree: `scenes(action="info", scene_path="<scene>.tscn")`
   - Verify every physics body and Area has a CollisionShape child. A body without a shape = invisible to physics.

3. **Wrong body type**:
   - `StaticBody2D`: immovable (walls, floors)
   - `CharacterBody2D`: player/NPC movement via `move_and_slide()`
   - `RigidBody2D`: physics-driven (projectiles, debris)
   - Common mistake: using `RigidBody2D` for a player character, then fighting the physics engine

4. **Script velocity issues**:
   - Read the script: `scripts(action="read", script_path="res://scripts/<name>.gd")`
   - Check if `velocity` is being set before `move_and_slide()`
   - Check if gravity is applied in `_physics_process` (not `_process`)
   - Check if `delta` is used for frame-independent movement

## Signals Decision Tree

1. **Connection exists?**
   - List all connections: `signals(action="list", scene_path="<scene>.tscn")`
   - Missing connection = signal silently does nothing

2. **Signature match?**
   - Signal definition parameters must match handler function parameters
   - `signal health_changed(new_hp: int)` requires handler `func _on_health_changed(new_hp: int)`
   - Extra or missing parameters = Godot error at runtime

3. **Signal emitted?**
   - Add `print("signal emitted")` before `emit_signal()` / `signal.emit()`
   - If not printed, the emit call is never reached (logic bug)

4. **Callable valid?**
   - If connected via code: target node must exist when `connect()` runs
   - If target is freed, signal emits to invalid callable = error

## Rendering Decision Tree

1. **Visibility**:
   - `visible` property = false? Check node and ALL parents (parent invisible = children invisible)
   - `modulate.a` = 0? (fully transparent)

2. **Z-index**:
   - Lower z-index renders behind higher z-index
   - `z_as_relative` = true means z_index is relative to parent
   - Sprite behind a TileMapLayer? Check z_index values on both

3. **Material/shader**:
   - CanvasItemMaterial or ShaderMaterial overriding appearance?
   - Shader compilation errors make object invisible (check Output panel)

4. **Viewport issues**:
   - SubViewport not updating? Check `render_target_update_mode`
   - Camera2D not active? Only one Camera2D should have `enabled = true` per viewport

## Navigation Decision Tree

1. **NavigationRegion setup**:
   - `NavigationRegion2D`/`3D` must exist in scene
   - Must have a `NavigationPolygon`/`NavigationMesh` resource assigned

2. **Navigation mesh baked?**
   - Mesh must be baked (either in editor or via `bake_navigation_mesh()`)
   - Unbaked mesh = no paths available

3. **NavigationAgent config**:
   - `path_desired_distance`: how close before moving to next path point
   - `target_desired_distance`: how close to target before stopping
   - Values too small = agent oscillates; too large = imprecise

4. **Path calculation**:
   - Call `NavigationAgent.set_target_position()` then check `get_next_path_position()`
   - If returns current position, no valid path exists (check mesh coverage)

## Input Decision Tree

1. **Input Map**:
   - List actions: `input_map(action="list")`
   - Check `project.godot` for `[input]` section

2. **Action name match**:
   - `Input.is_action_pressed("jump")` -- exact string match required
   - Typo in action name = silently returns false (no error!)

3. **Event processing**:
   - `_input()` vs `_unhandled_input()` -- if another node consumes the event, `_unhandled_input` never fires
   - `set_process_input(false)` disables `_input()` on that node

4. **Conflicts**:
   - Two actions on same key = both fire
   - UI elements (Button, LineEdit) consume input events before game nodes

## Diagnostic Steps

For any category:

1. **Inspect the scene tree**: `scenes(action="info", scene_path="<scene>.tscn")`
2. **Read relevant scripts**: `scripts(action="read", script_path="res://scripts/<name>.gd")`
3. **Check properties**: `nodes(action="get_property", scene_path="<scene>.tscn", name="<node_path>", property="<name>")`
4. **Run the scene**: `project(action="run", scene_path="<scene>.tscn")` and check output for errors
5. **Report findings**: present root cause and specific fix (property change, missing node, script edit)

## When to Use

- Any "it doesn't work" debugging scenario in Godot
- Systematic elimination when the cause is not obvious
- Verifying correct setup of physics, signals, rendering, navigation, or input

