Debugging a Crash¶
When you click Test Run and the generated app crashes instead of opening, there's a predictable flow for getting it working. This page walks through it.
The happy path: let auto-fix handle it¶
For most crashes, Whittl's auto-fix catches the error and tries to patch it automatically:
- You click Test Run.
- The app crashes with a traceback.
- Whittl reads the traceback, identifies the failure line, and activates auto-fix.
- The status bar shows "Fixing error..." with cycling dots.
- Auto-fix does a surgical edit (typically one round, maybe up to 5) and re-runs.
- If it works, the app launches.
On Claude Haiku or an OpenRouter cheap model, a typical auto-fix round costs about a penny. The hard cap is 5 rounds — beyond that, auto-fix gives up and hands control back to you.
Watch the terminal panel
The terminal panel at the bottom of the code editor shows stdout/stderr from the crashed app. Reading the raw traceback there often tells you what's wrong faster than waiting for auto-fix to figure it out.
The terminal panel¶
The Terminal tab in the preview panel serves two purposes in one pane: it shows your app's live output when you hit Test Run, and it lets you run arbitrary commands in the project folder. Most of the time you're looking at it because something crashed and you want to read the traceback.
What you see there¶
- Live Test Run output — when you press F5, your app's stdout streams into this pane in real time. Stderr goes in too, in red, so tracebacks stand out. An exit-code chip appears at the bottom when the app exits:
Done(green) on clean exit,Exit code: N(red) on error,Timeouton long-running captures. - Command echoes — anything you type into the input box at the bottom echoes back as
$ <command>in green so you can tell it apart from your app's own output. - Color coding — stdout is near-white, stderr is red, command echo is green, exit-code chip colored by success. This is consistent across both "my app crashed" and "my command failed" flows.
Running commands¶
Type into the input field at the bottom and press Enter (or click Run). The command runs in your current project folder — pwd will show the right place automatically. No need to cd first.
Common uses:
pip list # what's installed in this project's env
pip install requests # add a package
pip show pyside6 # version + install path
python --version # which Python is running
python -c "import flet; print(flet.__version__)" # one-liner test
python scripts/seed_db.py # run something other than main.py
venv auto-routing¶
If your project has a venv/ subfolder at its root, python and pip commands automatically route through that venv:
pip install requestslands in<project>/venv/, not Whittl's bundled runtimepython main.pyruns under the project venv's Python, not the bundled one
This is the right behavior for projects that need pinned dependency versions or that you plan to ship separately. If your project has no venv/, commands run against Whittl's bundled Python. Either way, nothing pollutes your system Python.
What's NOT supported¶
The terminal runs each command as a single process via subprocess, not through a shell. That means shell features don't work:
- No pipes —
cat file | grep foodoes nothing useful - No redirects —
python script.py > out.txtwon't capture output to file - No chains —
pip install X && python main.pyruns only the first bit - No glob expansion —
rm *.pyctreats*.pycas a literal filename - No environment variable syntax —
echo $PATHwon't expand
For anything complex, drop out to your OS shell (Windows Terminal, bash, etc.) in the project folder. The Whittl terminal is a convenience pane, not a replacement for a real shell.
Timeout¶
Each command has a 60-second timeout. If it hasn't completed, Whittl kills it and shows [Command timed out after 60s]. Fine for typical pip / Python commands; a problem if you kick off a big install or a long compile. For those, use your OS shell.
Clear button¶
The toolbar above the terminal has a Clear button that wipes the pane without touching anything else. Useful between Test Runs when the previous app's output is cluttering things.
When auto-fix doesn't resolve it¶
If auto-fix hits the round cap or oscillation guard, you'll see a message like:
Auto-fix stopped after 5 rounds without resolving the error. A competent fix usually lands in 1–3 rounds; more than this means the model is flailing.
Or:
Same error detected 3 times in a sliding window. Aborting to prevent token burn.
At this point, time to intervene manually. Four strategies, in order of effort:
1. Stronger model¶
The cheap model hit a ceiling. Switch to Claude Sonnet or Gemini 2.5 Pro and prompt:
"The app crashes on Run with this traceback: [paste error]. Fix it."
Premium models solve some things cheap ones can't. Costs a bit more per fix, but when you've burned 5 rounds without progress, the premium model's single fix pays for itself.
2. Be specific¶
Maybe the AI doesn't understand WHICH error to fix. Rewrite your fix prompt with specifics:
- Paste the full traceback, not a summary
- Name the file and function
- Describe what should happen instead of the crash
"In ui/main.py, the on_save_clicked method references self.filename which doesn't exist. Looking at the class, the attribute is called self.current_file. Rename the reference."
3. Manual edit¶
Sometimes the fix is obvious to you and the AI is going in circles. Just fix it yourself:
- Click the file tab showing the error
- Whittl jumps to the error line automatically (red highlight)
- Edit, save (Ctrl+S)
- Test Run again
Then keep going with the AI from a fresh prompt. Whittl will work with your manual fix as the new baseline.
4. Rollback and re-prompt¶
The last generation was a bad direction. Open the History panel, restore to before the problematic change, and try a different prompt:
- Same request, different wording
- Break the request into two smaller steps
- Switch to a different model (maybe the current one has a blind spot)
Reading a traceback¶
If you're new to Python, the traceback format can look noisy. The useful parts:
Traceback (most recent call last):
File "C:\Users\lynde\.whittl\projects\app_abc123\main.py", line 47, in <module>
from ui.window import MainWindow
File "C:\Users\lynde\.whittl\projects\app_abc123\ui\window.py", line 12, in <module>
from PySide6.QtWidgets import QMainWindowd
ImportError: cannot import name 'QMainWindowd' from 'PySide6.QtWidgets'
What matters:
- Last line — the actual error type and message.
ImportError: cannot import name 'QMainWindowd'tells you: typo inQMainWindowd→ should beQMainWindow. - Second-to-last
Fileline — where the error actually happened.ui/window.py, line 12points you at the offending line. - Earlier
Filelines — how the program got to the crash. Only matters if the fix isn't where the error points.
Most Whittl crashes fall into a handful of categories:
| Error type | Typical cause | Typical fix |
|---|---|---|
ModuleNotFoundError: No module named 'X' |
AI used a package that isn't installed or assumed a local module | Auto-install usually handles it; otherwise pip install manually or rename |
ImportError: cannot import name 'Y' from 'Z' |
Typo in import, or symbol moved between Qt versions | AI fixes typos; Qt6 migrations need from PyQt6 → from PySide6 |
AttributeError: 'X' object has no attribute 'y' |
AI used a method that doesn't exist, or referenced the wrong object | Usually AI can fix from the traceback |
TypeError: X takes N positional arguments but M were given |
Signature mismatch | Specific AI fix; easy |
NameError: name 'X' is not defined |
Variable scope issue, or import missing | Context-sensitive; usually AI handles it |
IndentationError |
Bad generation output | Auto-fix catches most; manual fix if it slips through |
SyntaxError |
Truncated code or bad parsing | Regenerate that file; something went wrong mid-stream |
Print debugging¶
When you need to understand what a variable actually is:
# Before:
result = process_data(user_input)
# After:
print(f"[DEBUG] user_input = {user_input!r}", flush=True)
result = process_data(user_input)
print(f"[DEBUG] result = {result!r}", flush=True)
The !r shows the repr() which disambiguates "5" (string) from 5 (int). The flush=True ensures output appears immediately rather than being buffered.
Whittl's terminal panel surfaces this output in real time — you can watch the prints happen as the app runs.
When the AI refuses to fix something¶
Rare but real. The AI might:
- Claim the code is already correct (when it clearly isn't)
- Apply an irrelevant fix
- Spin in circles on a philosophical point about Python semantics
These usually mean the model has a blind spot on your specific problem. Switch backends and try again. Gemini 2.5 Pro and Claude Sonnet have different strengths — one often sees what the other misses.
Known failure patterns¶
Flet apps that work in Test Run but crash on Android¶
Flet's mobile runtime has different API surface than desktop Flet. Things like window management, file dialogs, and some widgets behave differently. See Mobile Builds for Flet-mobile specifics.
PySide6 app with "QApplication must be instantiated before QWidget"¶
You have a QWidget(...) being created at module import time before app = QApplication(...) runs. Common cause: a default argument that calls a Qt constructor. Move the widget creation into __init__ or into a function.
SystemError: initialization of <module> raised unreported exception¶
Something with how Python's import system is handling your files. Usually caused by circular imports. Restructure so file A doesn't need to import file B which imports file A.
"Cannot mix different versions of PySide6"¶
You installed a PySide6 package that conflicts with Whittl's bundled version. Fix:
# In Whittl's terminal panel
pip uninstall PySide6
pip install PySide6==6.8.0 # whatever version Whittl ships
When it's not a crash¶
Sometimes the app "works" but doesn't do what you wanted:
- Button does nothing when clicked
- Data doesn't persist between runs
- Layout is subtly broken
These aren't crashes — they're missing or incorrect functionality. Iterate with the AI just like any other follow-up, describing the gap between what you see and what you want.
What's next¶
- Auto-fix Rules — the rules that catch common mistakes automatically
- Common Issues — specific known problems and their fixes
- Reporting Bugs — if you've hit something genuinely broken