Debugging

Everyone writes broken code. The skill is fixing it calmly.

When something goes wrong, Bloom doesn't just say "error." It tries to figure out what you meant and tells you how to fix it. This chapter shows you how to read those messages and the tools Bloom gives you to track down problems.

Reading an Error Message

A Bloom error has up to three parts: what went wrong, a suggestion, and a usage hint. For example, calling a circle with too few arguments produces:

circle expects 3 argument(s) but got 2

  Check the arguments: circle(x, y, radius)
  You might be missing some arguments
  Usage: circle(x, y, radius) - Draw a circle

The first line is the problem. The indented lines are help. Read them top to bottom and the fix is usually obvious.

Typos Get a "Did You Mean?"

Misspell a function or variable and Bloom finds the closest real name for you:

Undefined variable 'circel'

  Did you mean 'circle'?
  Usage: circle(x, y, radius) - Draw a circle

Try it yourself — this sketch has a typo. Run it, read the suggestion, then fix it:

fn setup() { size(300, 200) } fn draw() { background(rgb(30, 30, 40)) fill(coral) circel(150, 100, 40) }
How does it know? Bloom measures how many single-character edits separate your typo from every name it knows, and suggests the nearest one. The full algorithm — and the cross-language keyword catches below — are explained on the error system internals page.

Coming From Another Language?

Bloom recognizes keywords from Python and JavaScript and redirects you to the Bloom way:

Warnings Before You Even Run

Some code is valid but probably not what you wanted. Bloom scans for these and shows a warning without stopping your sketch — for example using = where you meant ==, calling circle(100, 100) without a radius, or writing print "hi" without parentheses. Treat warnings as a friendly second opinion.

Print Your Way to the Answer

The oldest debugging trick still works best: print a value to see what it actually is. Use print() with a template string (note the { } placeholders) to peek at variables as the sketch runs:

let x = 0 fn setup() { size(300, 200) } fn draw() { background(rgb(30, 30, 40)) x = x + 1 // Watch the value in the console print("frame {frame}, x is {x}") fill(coral) circle(x % width, 100, 30) }

Watch It Run, One Step at a Time

For trickier bugs, you can slow everything down. The How Bloom Works explorer includes a live debugger that re-runs your program and records a snapshot at every statement — which line ran and what every variable held at that moment. Step forward through a loop and watch the counter and your values change in real time.

This is the same step/pause machinery the playground's controls use, driven by the runtime's step() method. If you want to know how pausing mid-execution works under the hood, see the runtime internals.

A Debugging Checklist

Curious how errors are built? Every message on this page is generated by src/lang/errors.ts. The error system deep dive walks through the actual code that produces them.