Use when errors occur deep in execution and you need to trace back to find the original trigger - systematically traces bugs backward through call stack, adding instrumentation when needed, to identify source of invalid data or incorrect behavior
Bugs often manifest deep in the call stack (git init in wrong directory, file created in wrong location, database opened with wrong path). Your instinct is to fix where the error appears, but that's treating a symptom.
Core principle: Trace backward through the call chain until you find the original trigger, then fix at the source.
digraph when_to_use {
"Bug appears deep in stack?" [shape=diamond];
"Can trace backwards?" [shape=diamond];
"Fix at symptom point" [shape=box];
"Trace to original trigger" [shape=box];
"BETTER: Also add defense-in-depth" [shape=box];
"Bug appears deep in stack?" -> "Can trace backwards?" [label="yes"];
"Can trace backwards?" -> "Trace to original trigger" [label="yes"];
"Can trace backwards?" -> "Fix at symptom point" [label="no - dead end"];
"Trace to original trigger" -> "BETTER: Also add defense-in-depth";
}
Use when:
Error: git init failed in C:\Users\developer\project\src\MyProject.Core
What code directly causes this?
await ProcessHelper.RunAsync("git", "init", workingDirectory: projectDir);
WorktreeManager.CreateSessionWorktreeAsync(projectDir, sessionId)
→ called by Session.InitializeWorkspaceAsync()
→ called by Session.CreateAsync()
→ called by test at Project.CreateAsync()
What value was passed?
projectDir = "" (empty string!)Where did empty string come from?
var context = SetupCoreTest(); // Returns { TempDir = "" }
await Project.CreateAsync("name", context.TempDir); // Accessed before setup!
When you can't trace manually, add instrumentation:
// Before the problematic operation
public static async Task GitInitAsync(string directory)
{
var stackTrace = Environment.StackTrace;
Console.Error.WriteLine($"DEBUG git init: {new {
Directory = directory,
CurrentDirectory = Environment.CurrentDirectory,
Environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT"),
StackTrace = stackTrace
}}");
await ProcessHelper.RunAsync("git", "init", workingDirectory: directory);
}
Critical: Use Console.Error.WriteLine() in tests (not ILogger - may not show)
Run and capture:
dotnet test --logger "console;verbosity=detailed" 2>&1 | findstr "DEBUG git init"
Analyze stack traces:
If something appears during tests but you don't know which test:
Use the bisection script: @find-polluter.sh
./find-polluter.sh '.git' 'src/**/*.test.ts'
Runs tests one-by-one, stops at first polluter. See script for usage.
Symptom: .git created in packages/core/ (source code)
Trace chain:
git init runs in current directory ← empty working directory parametercontext.TempDir before setup{ TempDir = "" } initiallyRoot cause: Top-level variable initialization accessing empty value
Fix: Made TempDir a property that throws if accessed before setup
Also added defense-in-depth:
digraph principle {
"Found immediate cause" [shape=ellipse];
"Can trace one level up?" [shape=diamond];
"Trace backwards" [shape=box];
"Is this the source?" [shape=diamond];
"Fix at source" [shape=box];
"Add validation at each layer" [shape=box];
"Bug impossible" [shape=doublecircle];
"NEVER fix just the symptom" [shape=octagon, style=filled, fillcolor=red, fontcolor=white];
"Found immediate cause" -> "Can trace one level up?";
"Can trace one level up?" -> "Trace backwards" [label="yes"];
"Can trace one level up?" -> "NEVER fix just the symptom" [label="no"];
"Trace backwards" -> "Is this the source?";
"Is this the source?" -> "Trace backwards" [label="no - keeps going"];
"Is this the source?" -> "Fix at source" [label="yes"];
"Fix at source" -> "Add validation at each layer";
"Add validation at each layer" -> "Bug impossible";
}
NEVER fix just where the error appears. Trace back to find the original trigger.
In tests: Use Console.Error.WriteLine() not ILogger - logger may be suppressed
Before operation: Log before the dangerous operation, not after it fails
Include context: Directory, current directory, environment variables, timestamps
Capture stack: Environment.StackTrace shows complete call chain
From debugging session (2025-10-03):
npx skills add alexsandrocruz/root-cause-tracing下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer