Prompting for Debugging and Error Analysis

La Lakshmi Priya Updated 06 Nov 2026
10 min read ·Lesson 93 of 100

What Makes Debugging Prompts Effective When code fails, it is tempting to paste the error message and ask "How do I fix this?" Sometimes that works. Often, it produces a confident fix for the wrong problem, because the model has to guess the code, the inputs, the environment, and what you expected.

Effective debugging with a model follows the same discipline as debugging without one:

  1. Collect evidence: error, code, input, expected vs actual, environment
  2. Form hypotheses: possible causes, ranked by likelihood
  3. Test hypotheses: add checks or logs, reproduce, narrow down
  4. Fix the cause: smallest change that addresses the root cause
  5. Prove the fix: a test that failed before and passes after This lesson provides prompts for each stage and a small tool that turns a long traceback into the compact evidence a model needs. Debugging multi-step prompt chains is covered separately in Lesson 74.

Stage 1: Collect the Evidence What to Include Evidence Why It Matters Full error message and traceback Shows the exception type, message, and where it happened The relevant code The model cannot fix code it cannot see The input that triggered it Many bugs occur only for specific inputs Expected vs actual behavior Defines what "fixed" means, especially for bugs without errors Environment Language, framework, and library versions What you already tried Avoids repeated suggestions (Lesson 6) Recent changes Bugs often appear right after a change Summarizing a Long Traceback A traceback lists the chain of function calls that led to an error. Framework tracebacks are often long, and most frames are inside the framework, not your code. The frames in your code are usually where the problem is. A small parser can extract them:

import json import re

def summarize_traceback(traceback_text: str, project_marker: str = "myapp") -> dict: """Extract the error line and the frames that belong to the project.""" error_line = traceback_text.strip().splitlines()[-1] frames = re.findall(r'File "([^"]+)", line (\d+), in (\w+)\n\s+(.+)', traceback_text) project_frames = [ f"{path}:{line} in {function}: {code.strip()}" for path, line, function, code in frames if project_marker in path ] return {"error": error_line, "project_frames": project_frames, "total_frames": len(frames)}

traceback_text = '''Traceback (most recent call last): File "/usr/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/home/dev/myapp/courses/views.py", line 42, in enroll total = course_total(course.fee, discount, gst) File "/home/dev/myapp/courses/pricing.py", line 12, in course_total return round(fee (100 - discount) / 100 (100 + gst) / 100) TypeError: unsupported operand type(s) for -: 'int' and 'str' '''

print(json.dumps(summarize_traceback(traceback_text), indent=2)) Output:

{ "error": "TypeError: unsupported operand type(s) for -: 'int' and 'str'", "project_frames": [ "/home/dev/myapp/courses/views.py:42 in enroll: total = course_total(course.fee, discount, gst)", "/home/dev/myapp/courses/pricing.py:12 in course_total: return round(fee (100 - discount) / 100 (100 + gst) / 100)" ], "total_frames": 3 } Code Explanation The error line is the last line of a Python traceback: the exception type and message. The regular expression captures each frame's file path, line number, function name, and the line of code shown below it. project_marker filters frames whose path contains your project folder name. Framework frames are excluded, but still counted in total_frames. The summary points directly to the problem: discount is a string where a number is expected. Line 42 in views.py passes it to course_total. Because the value probably comes from a form or URL parameter, the fix likely belongs in the view, which should convert and validate the input, not in the pricing function.

Note: Remove secrets, personal data, and internal hostnames from tracebacks and logs before sending them to a model.

Stage 2: Form Ranked Hypotheses Prompt Help me debug this problem. Do not write a fix yet.

Environment: {environment} Expected behavior: {expected} Actual behavior: {actual} Input that triggers it: {input} What I already tried: {tried}

{error_summary}

{relevant_code_with_line_numbers}

List the 3 most likely causes, ranked. For each:

  • Why the evidence supports it
  • What evidence would confirm or rule it out
  • The quickest check to perform Why It Works "Do not write a fix yet" prevents the most common debugging mistake: applying a guessed fix before understanding the cause. Ranked hypotheses keep alternatives visible. The first guess is not always right. A check per hypothesis turns ideas into actions that produce evidence. Example Hypotheses for the Traceback Above
  1. The discount value comes from request data (a string) and is passed without conversion. Check: print type(discount) in the view.
  2. The Course model stores the discount as a CharField. Check: the model definition.
  3. A default value is set as a string somewhere, such as discount = "0". Check: search for where discount is assigned. Stage 3: Test Hypotheses Prompt for Diagnostic Checks For the hypothesis "{hypothesis}", give me the smallest diagnostic step to confirm or rule it out: a log statement, an assertion, or a command to run. Show exactly where to put it in , and what output would confirm the hypothesis. Prompt for a Minimal Reproduction A minimal reproduction is the smallest piece of code that shows the bug, without the rest of the application. It makes the cause obvious and is ideal for tests and bug reports.

Create a minimal, self-contained Python script that reproduces the error in , using only the logic from that is needed. Use fixed sample values instead of database or request data. Narrowing Down With Differences When something "used to work", compare the working and broken states:

This code worked before the change in and fails after it with . Which part of the change is most likely responsible, and why? Tools such as git bisect can find the commit that introduced a bug automatically, by testing commits in a binary search.

Stage 4: Fix the Root Cause Prompt The cause is confirmed: {confirmed_cause}

Propose the smallest fix that addresses this root cause.

  • Change only what is necessary.
  • Fix the cause, not the symptom (for example, validate input where it enters the system rather than adding try/except where it fails).
  • Explain why the fix works, and whether any other code could have the same problem.

{relevant_code} Symptom vs Root-Cause Fixes Problem Symptom Fix Root-Cause Fix discount arrives as a string int(discount) inside course_total Validate and convert discount in the view or form where request data enters A query sometimes returns no row Wrap in try/except and return a default Find why the row is missing, or handle the "not found" case explicitly and correctly A loop skips the last item Add a special case for the last item Fix the loop's range Symptom fixes make the error disappear but often hide the real problem, which reappears elsewhere.

Avoid Silencing Errors A common model suggestion is to wrap failing code in a broad try/except that ignores errors. Unless failure is truly expected and handled meaningfully, this hides bugs and makes future debugging harder. Ask explicitly: "Do not suppress exceptions unless the error is expected and handled."

Stage 5: Prove the Fix Prompt Write a pytest test that reproduces the bug described in : it must fail with the current code and pass with the fix. Use the minimal reproduction values. Why This Matters A test that fails before the fix proves it actually reproduces the bug. A test that passes after proves the fix works. The test stays in the test suite as a regression test, so the bug cannot return unnoticed (Lessons 74 and 118). Debugging Bugs Without Errors Some of the hardest bugs produce no error: wrong totals, missing records, or wrong display. For these, the expected vs actual description is essential.

Prompt This function returns the wrong result, without any error.

Input: {input} Expected output: {expected} Actual output: {actual}

{numbered_code}

Trace the execution for this input step by step, showing variable values, and identify the first line where the actual values differ from what is needed for the expected output. This uses the execution trace from Lesson 92. The "first line where values differ" is the same principle as finding the first failing step in a chain (Lesson 74).

Analyzing Logs Prompt Analyze the application logs in from the period when users reported {problem}.

  1. Group related entries and identify the main error patterns.
  2. For each pattern: how often it occurs, when it started, and which request paths or users are affected.
  3. Identify the earliest entry that suggests the cause.
  4. List what additional information would help confirm the cause.

Do not assume a cause the logs do not support. Practical Advice Filter logs in code first, by time range, severity, or request ID, so the prompt contains only relevant entries. Count patterns in code for exact frequencies (Lesson 72). Let the model interpret patterns rather than count them. Mask personal data and secrets before sending logs. Common Mistakes Mistake 1: Pasting Only the Error Message What it is: "Fix TypeError: unsupported operand type(s)."

Why it happens: The error seems to describe the problem.

What it causes: Generic advice that may not apply to your code.

How to fix it: Include code, input, expected and actual behavior, environment, and the traceback.

Mistake 2: Fixing Before Understanding What it is: Applying the first suggested fix without confirming the cause.

Why it happens: It is the fastest path to a green screen.

What it causes: Symptom fixes and new bugs.

How to fix it: Ask for ranked hypotheses and checks before fixes.

Mistake 3: Silencing Errors What it is: Accepting fixes that catch and ignore exceptions.

Why it happens: The error disappears.

What it causes: Hidden bugs and corrupted data later.

How to fix it: Fix the root cause; catch only expected errors and handle them meaningfully.

Mistake 4: No Regression Test What it is: Fixing a bug without adding a test.

Why it happens: The fix seems obviously correct.

What it causes: The same bug returns after later changes.

How to fix it: Add a test that fails before the fix and passes after.

Mistake 5: Sending Secrets in Logs or Tracebacks What it is: Pasting raw logs that contain tokens, passwords, or personal data.

Why it happens: Debugging is urgent.

What it causes: Exposure of sensitive information.

How to fix it: Mask secrets and personal data before sending anything.

Best Practices Collect complete evidence. Error, code, input, expected vs actual, environment, attempts, and recent changes.

Summarize long tracebacks. Focus on frames in your own code.

Separate diagnosis from fixing. Ranked hypotheses, then checks, then fixes.

Use minimal reproductions. They make causes obvious and become tests.

Fix root causes, not symptoms. Validate input where it enters the system.

Prove every fix with a test. Failing before, passing after, kept as a regression test.

Protect sensitive data. Mask it before it leaves your environment.

Try It Yourself Exercise 1: Summarize a Real Traceback Trigger an error in one of your Django or Python projects, copy the full traceback, and run summarize_traceback() with your project folder name as the marker. Use the summary in the hypothesis prompt and compare the ranked causes with the actual cause.

Exercise 2: Bug Without an Error Write a function that calculates a course total but applies GST before the discount instead of after. Give the model the input, expected output, actual output, and code, and ask for a trace that finds the first wrong line. Then write a regression test.

Exercise 3: Symptom vs Root Cause For each scenario, write a symptom fix and a root-cause fix: a form field that sometimes arrives empty, a date string in two different formats, and a list that is sometimes None instead of empty. Discuss which fix a model suggested first when you asked for "a fix".

0 Comments

Reviewed before they appear

No comments yet.

Prompt Engineering
Prompt Engineering Introduction How Large Language Models Respond to Prompts Prompting Basics Elements of an Effective Prompt Writing Clear Instructions for AI Models Adding Context to a Prompt Providing Input Data in Prompts Using Output Indicators and Response Formats Prompt Formatting: Questions, Instructions, and Templates General Tips for Designing Better Prompts Common Prompt Engineering Mistakes Iterative Prompt Design and Refinement Understanding Instruction, Context, Input, and Output How Specificity and Conciseness Affect Prompt Quality Breaking Large Tasks into Smaller Prompting Tasks Zero-Shot Prompting Zero-Shot Prompting Examples for Everyday Tasks Zero-Shot Text Classification Zero-Shot Question Answering Zero-Shot Summarization Zero-Shot Translation Zero-Shot Prompting for Information Extraction When to Use Zero-Shot Prompting Limitations of Zero-Shot Prompting Improving Weak Zero-Shot Prompts Few-Shot Prompting One-Shot Prompting vs Few-Shot Prompting Choosing Good Examples for Few-Shot Prompts Formatting Examples in Few-Shot Prompts Few-Shot Classification with Examples Few-Shot Prompting for Structured Output Few-Shot Prompting Zero-Shot vs Few-Shot Prompting Role Prompting and Persona Instructions Instruction-Based Prompting Task-Oriented Prompt Templates Using Delimiters to Separate Prompt Sections Prompt Templates with Variables Chain-of-Thought Prompting Zero-Shot Chain-of-Thought Prompting Few-Shot Chain-of-Thought Prompting Automatic Chain-of-Thought (Auto-CoT) When Chain-of-Thought Prompting Helps Limitations of Chain-of-Thought Prompting Self-Consistency Prompting Comparing Chain-of-Thought and Self-Consistency Tree of Thoughts (ToT) Prompting Exploring Multiple Solutions with Tree of Thoughts Least-to-Most Prompting Complexity-Based Prompting Maieutic Prompting Self-Consistency: Sampling Multiple Reasoning Paths Self-Consistency for Arithmetic and Logic Tasks Tree of Thoughts: Search, Evaluation, and Backtracking Meta Prompting Generate Knowledge Prompting Directional Stimulus Prompting Program-Aided Language Models (PAL) React: Reasoning and Acting with Language Models Reflexion: Improving Agents Through Feedback Prompt Chaining Designing Multi-Step Prompt Chains Decomposing Complex Tasks into Prompt Chains Automatic Prompt Engineer (APE) Active-Prompt: Selecting Useful Reasoning Examples Optimizing Prompts Systematically Prompt Iteration and Versioning Building Reusable Prompt Libraries Testing Prompt Variants Prompt Chaining Fundamentals Passing Outputs Between Prompt Steps Prompt Chains for Summarization and Extraction Validating Intermediate Results in a Prompt Chain Debugging a Multi-Step Prompt Workflow Graph Prompting Multimodal Chain-of-Thought Prompting Automatic Reasoning and Tool-Use (ART) Prompting for Tool Selection and Use Combining Prompting Techniques for Complex Tasks Prompts for Text Summarization Prompts for Information Extraction Prompts for Text Classification Prompts for Question Answering Prompts for Sentiment Analysis Prompts for Rewriting and Editing Prompts for Translation and Localization Prompts for Brainstorming and Creative Writing Prompts for Generating Structured Data Prompts for Explaining Technical Concepts Prompts for Generating and Reviewing Code Prompting for Code Generation Prompting for Code Explanation Prompting for Debugging and Error Analysis Prompting for Unit Test Generation Prompting for SQL Query Generation Prompting for API Documentation Prompting for Technical Documentation Using Prompting to Extract Requirements Creating JSON-Style Structured Responses with Prompts Designing Prompts for Repeatable Developer Workflows
Ask about this post
AI Ask about this post

Ask questions about Prompting for Debugging and Error Analysis and get answers drawn from it.

Signed-in readers only.