Fix a Broken Docassemble Interview: Common YAML/Logic Issues and How to Solve Them


Police investigator interrogating criminal in interrogation room. Suspect and officer sitting at table with lamp, detective asking question flat vector illustration. Crime, criminal psychology concept

Nothing is more frustrating than a Docassemble interview that almost works—until it suddenly throws an error, loops forever, or generates a blank document right when you need it.

If you’ve ever shipped a docassemble app for intake, forms, or document assembly, you already know: most “broken” interviews aren’t broken because Docassemble is unreliable. They’re broken because small YAML or logic decisions quietly snowball into runtime failures.

This guide is a practical, human-friendly playbook for docassemble debugging-the real issues that cause interviews to fail, how to spot them quickly, and how to fix them without guesswork.

First: How Docassemble “thinks” (the mental model that makes debugging easier)

Docassemble runs interviews like a dependency engine:

  • You reference a variable (e.g., user.name.first)
  • Docassemble asks: “Do I know this value yet?”
  • If not, it finds a block that defines it (question, code, objects, etc.)
  • It runs blocks until the variable is known
  • Then it continues

Most bugs happen when:

  • a variable is referenced before it’s defined
  • a block meant to define it never runs (because logic prevents it)
  • you accidentally define the wrong variable name (typo / casing / scope)
  • your mandatory blocks keep re-triggering

The most common “broken interview” issues (and how to fix them)

1) “NameError / Undefined variable” (the #1 issue)

Symptom

  • Error like: NameError: name ‘x’ is not defined
  • Or a template field shows blank unexpectedly

Cause

  • You used a variable before it was set
  • Or the defining block doesn’t run due to a condition

Fix checklist

  • Search for the variable usage first (template, code, question text)
  • Ensure there is exactly one clear place where it’s defined
  • Make sure the block that defines it can actually run

Common example
You use user_phone in a template but only ask it inside an if: branch that doesn’t trigger.

2) “YAML indentation” mistakes (small whitespace, big damage)

Symptom

  • YAML parse errors
  • Interview fails to load
  • Blocks behave weirdly

Cause

  • Wrong indentation under question:, fields:, choices:, or if:
  • Mixing tabs and spaces

Fix checklist

  • Use spaces only (never tabs)
  • Align list items carefully under fields: and choices:
  • Validate your file structure: every block starts with

3) “Mandatory block loops forever”

Symptom

  • Interview keeps re-running the same screen
  • You can’t progress past a step
  • It feels like Docassemble is “stuck”

Cause

  • A mandatory: True block keeps evaluating as incomplete
  • The block keeps referencing variables that are never resolved properly
  • A need() call keeps re-triggering

Fix checklist

  • Temporarily comment out the mandatory block and confirm flow resumes
  • Move complex logic into a separate code block with clear variable outputs
  • Avoid referencing variables inside mandatory that depend on conditional screens that never trigger

4) “I used the wrong variable name” (typos + casing)

Symptom

  • You think you set client_name, but later it’s empty
  • Or you see two similar variables (clientName vs client_name)

Cause

  • Docassemble treats variable names as exact identifiers

Fix checklist

  • Pick one naming style (snake_case is easiest)
  • Search the entire interview for similar spellings
  • Be consistent in templates too (${ client_name } vs ${ clientName })

5) “Question logic doesn’t run because of conditions”

Symptom

  • A screen never appears
  • Your interview skips steps unexpectedly

Cause

  • An if: condition is wrong
  • A boolean defaults to false because you never asked it

Fix checklist

  • Ensure you asked the gating variable earlier
  • Add temporary debug output (see code section below)
  • Convert confusing conditions into explicit booleans

Example:
Instead of repeating if: user_role == “staff” and case_type in (…), define:
is_staff_case = (user_role == “staff” and case_type in (…))

6) “Document output is blank or missing fields”

Symptom

  • PDF/DOCX generates, but key fields are empty
  • Some text shows, some doesn’t

Cause

  • Template uses variables that were never set
  • You used a complex object incorrectly
  • Your template is referencing the wrong variable path

Fix checklist

  • Print the variables right before document generation
  • Ensure you’re populating what the template expects

Keep template variable names simple and flat when possible

A practical docassemble debugging workflow (use this every time)

  1. Reproduce the issue
    Do the exact steps that trigger it. Don’t “guess” from logs alone.
  2. Identify the failure type
  • YAML parse error (load-time)
  • Runtime error (undefined variable, type error)
  • Logic error (loop, missing step, blank output)
  1. Trace the variable
    Start from where it fails (template or code), then find:
  • where it should be defined
  • why that block didn’t run
  1. Simplify
    Temporarily remove conditions and make the variable asked directly.
    Once it works, add logic back gradually.
  2. Add lightweight debug prints
    Print state at key points (example below).
---
question: Debug snapshot
subquestion: |
  **user_role:** ${ user_role if defined('user_role') else "NOT SET" }  
  **case_type:** ${ case_type if defined('case_type') else "NOT SET" }  
  **client_name:** ${ client_name if defined('client_name') else "NOT SET" }  
  **needs_followup:** ${ needs_followup if defined('needs_followup') else "NOT SET" }
continue button field: debug_continue
---

B) Use defined() to prevent crashes while debugging

---
code: |
  if defined('client_name'):
      safe_client_name = client_name
  else:
      safe_client_name = "Unknown"
---

C) Avoid repeated logic in conditions (create clear booleans)

---
code: |
  is_staff = (user_role == "staff") if defined('user_role') else False
  is_intake_case = (case_type in ["family", "housing"]) if defined('case_type') else False
  show_extra_questions = is_staff and is_intake_case
---
---
question: Extra details
fields:
  - Additional notes: extra_notes
if: show_extra_questions
---

How to prevent breakage in future interviews

  • Keep interviews modular: one section = one clear output
  • Standardize variable naming (snake_case)
  • Keep “logic” in code blocks, not embedded everywhere
  • Generate documents only after a “final review” step
  • Build small test paths (happy path + 2 edge cases) before scaling

Final thoughts

A “broken” Docassemble interview usually isn’t a big, scary failure—it’s almost always a small YAML/logic mismatch that snowballs: a variable referenced too early, an if: that never triggers, or a mandatory block that keeps looping. The good news is that once you adopt a simple docassemble debugging rhythm—reproduce → trace the variable → simplify → add a quick debug snapshot—you’ll fix issues faster, ship more confidently, and spend way less time firefighting. Over time, those small habits turn your interviews into something teams can trust in production, not just in test runs.

Leave a Comment

Your email address will not be published. Required fields are marked *

en_USEnglish
Scroll to Top