Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Reading error messages

Nifty tries hard to explain problems in plain words and to suggest a fix. This page shows how to read an error, then lists the ones you’re most likely to meet.

Anatomy of an error

Error: `label` shows text; turn this `int` into text with "{…}"
   ╭─[ hello/main.nf:5:11 ]
   │
 5 │     label(count)
───╯
1 error
  • The first line says what’s wrong, and usually how to fix it.
  • hello/main.nf:5:11 is the file, the line (5) and the column (11).
  • The code below is the line itself.

Nifty reports every problem it finds in one go, not just the first, and the count is at the bottom. In an editor with Nifty support, the same errors appear as squiggles while you type.

When errors appear

WhenWhat finds itExample
Before runningnf check, nf run, nf dev and nf builda typo in a name, the wrong type
While runningnf run and nf devdividing by zero, a list item that isn’t there

Most mistakes are caught before running. When an error happens while running, nf run stops the app and points at the line, just like a check error. nf dev points at the line too, but keeps the app open so you can save a fix.

Common errors

`label` shows text; turn this `int` into text with "{…}"

You gave label a number. Put it in a string with interpolation:

label(count)          // ✗
label("{count}")      // ✓

can't use `+` with `string` and `int`

You joined text and a number with +. Use interpolation instead:

label("Count: " + count)    // ✗
label("Count: {count}")     // ✓

can't use `+` with `int` and `float`

int and float don’t mix. Write both the same way: 2.0 * 1.5, or 2 * 3.

expected end of line, found `{`; put each statement on its own line

Usually a missing () on an element:

column { … }      // ✗
column() { … }    // ✓

`button` needs a `{ … }` block with what it does

Every button needs an action, even an empty one:

button("Later")        // ✗
button("Later") { }    // ✓

`text_field` needs a two-way binding to a `string`, such as `$name`

Controls that edit a value need a $. See Two-way bindings.

text_field(draft)      // ✗
text_field($draft)     // ✓

unknown name `count`

There’s no state, variable or parameter with that name. Check the spelling, and check that you declared it with state or let.

can't tell what this empty list holds; add a type such as `: [int]`

An empty list needs its type written out:

state todos = []              // ✗
state todos: [Todo] = []      // ✓

only declarations, `window(…)` and `menu(…)` can appear at the top level

Outside any window or function, you can only declare things: state, fn, view, struct, window and menu. Use state (not let) for top-level values.

only elements, `if` and `for` can appear here; put logic in a function or a button's action

You wrote a statement like count = 0 directly in a window or view. Move it into a button’s action or a function.

showing the UI can't change state; do that in a button's action

Something used to show the UI tried to change state, often a function call inside a label. See State.

a state's starting value can't use other state

state b = a isn’t allowed. Use a function that computes b from a instead.

`remaining` can reach its end without returning a `int`

Some path through the function finishes without a return. Often an if without an else; add a return at the end.

there is no item 3; the list has 2 (while running)

You read a list position that doesn’t exist. Positions start at 0, so a list of two has items 0 and 1. Check items.len() first.

can't divide by zero (while running)

Check the number you divide by isn’t 0 before dividing.

Still stuck?

Open an issue on GitHub with your code and the error. Confusing error messages count as bugs.