# Reading Zig Error Messages

### Reading Zig Error Messages

Sooner or later, every Zig beginner meets the compiler.

Not just the compiler that builds your program, but the compiler that refuses to build your program.

That is normal. Compiler errors are part of programming. They are not signs that you are bad at Zig. They are messages from the compiler saying, “This code does not make sense yet.”

Your job is to read the message carefully and fix one problem at a time.

#### Start with a Broken Program

Create a file named:

```text
main.zig
```

Put this code inside it:

```zig
const std = @import("std");

pub fn main() void {
    const name = "Zig"
    std.debug.print("Hello, {s}!\n", .{name});
}
```

There is a mistake here.

Run:

```bash
zig run main.zig
```

Zig will report an error because this line is missing a semicolon:

```zig
const name = "Zig"
```

It should be:

```zig
const name = "Zig";
```

This is one of the most common beginner errors.

#### The Shape of an Error Message

A Zig error message usually tells you several things:

| Part | Meaning |
|---|---|
| File name | Which file has the problem |
| Line number | Which line has the problem |
| Column number | Where on the line the problem appears |
| Error text | What Zig thinks is wrong |
| Code snippet | A small piece of the source code |

The exact formatting may vary, but the useful information is the same.

You want to find:

```text
file -> line -> column -> message
```

For example, an error may point to:

```text
main.zig:5:5
```

This means:

```text
file main.zig, line 5, column 5
```

Go there first.

#### Fix the First Error First

When the compiler prints many errors, beginners often try to read all of them.

Do not do that at first.

Start with the first error.

One small mistake can confuse the compiler and cause several later messages. If you fix the first error, the others may disappear.

For example, a missing semicolon can make the next line look wrong too. The compiler reports where it became confused, but the real cause may be just before that location.

A good rule:

```text
Fix the first error, then compile again.
```

#### Type Errors

Zig is a statically typed language.

That means Zig checks types before the program runs.

Try this program:

```zig
const std = @import("std");

pub fn main() void {
    const age: u32 = "ten";
    std.debug.print("{}\n", .{age});
}
```

This line is wrong:

```zig
const age: u32 = "ten";
```

The type `u32` means an unsigned 32-bit integer.

But `"ten"` is a string.

Zig will reject this because the value does not match the declared type.

The fix is to use a number:

```zig
const age: u32 = 10;
```

Or, if you really want text, change the meaning of the variable:

```zig
const age_text = "ten";
```

The compiler is not guessing what you meant. It checks what you wrote.

#### Unknown Names

Another common error is using a name that does not exist.

```zig
const std = @import("std");

pub fn main() void {
    std.debug.print("{}\n", .{answer});
}
```

The name `answer` has not been declared.

You need to create it first:

```zig
const std = @import("std");

pub fn main() void {
    const answer = 42;
    std.debug.print("{}\n", .{answer});
}
```

In Zig, names must be declared before they are used.

This helps keep programs readable. When you see a name, there should be a clear place where it was defined.

#### Unused Values

Zig is strict about unused values.

Try this:

```zig
pub fn main() void {
    const x = 10;
}
```

The variable `x` is never used.

Zig may report an error because unused local constants and variables often indicate mistakes.

If you are temporarily ignoring a value, assign it to `_`:

```zig
pub fn main() void {
    const x = 10;
    _ = x;
}
```

The underscore means:

```text
I know this value exists, and I intentionally discard it.
```

This is common while experimenting.

#### Wrong Format Strings

Printing errors are also common.

This code is wrong:

```zig
const std = @import("std");

pub fn main() void {
    const name = "Zig";
    std.debug.print("Hello, {}!\n", .{name});
}
```

For strings, use `{s}`:

```zig
const std = @import("std");

pub fn main() void {
    const name = "Zig";
    std.debug.print("Hello, {s}!\n", .{name});
}
```

Zig’s formatter is strict because it checks that the format string matches the arguments.

This may feel annoying at first, but it catches mistakes early.

#### Error Messages from Imports

If you write:

```zig
const foo = @import("foo.zig");
```

but `foo.zig` does not exist, Zig will report an import error.

The fix is one of these:

| Problem | Fix |
|---|---|
| File does not exist | Create the file |
| File name is wrong | Correct the name |
| File is in another folder | Use the right path |
| You are building from the wrong directory | Run the command from the project root |

For example, if the file is under `src/`:

```text
src/foo.zig
```

and `main.zig` is also under `src/`, this works:

```zig
const foo = @import("foo.zig");
```

But if you import from another location, paths must match the project layout.

#### Errors from Missing `try`

If a function can fail, Zig requires you to handle that possibility.

Example:

```zig
const std = @import("std");

fn mayFail() !void {
    return error.SomethingWentWrong;
}

pub fn main() void {
    mayFail();
}
```

The call is wrong because `mayFail()` can return an error.

You cannot ignore that error.

One fix is to use `try`, but then `main` must also be able to return an error:

```zig
const std = @import("std");

fn mayFail() !void {
    return error.SomethingWentWrong;
}

pub fn main() !void {
    try mayFail();
}
```

Notice the return type changed:

```zig
pub fn main() !void
```

The `!void` means `main` can return an error.

Zig forces error paths to be visible.

#### Read the Code Around the Error

The exact line number is important, but the real mistake may be nearby.

When you see an error, inspect:

| Place to check | Why |
|---|---|
| The error line | The compiler became confused there |
| The line before | Missing semicolon or brace may be there |
| The surrounding block | Braces may be mismatched |
| The function signature | Return type may be wrong |
| Imports | A missing file or wrong name may cause later errors |

Beginners often stare only at the marked line. Check the nearby lines too.

#### Use Small Programs While Learning

Small programs make errors easier to understand.

If your file has 20 lines, an error is easier to find.

If your file has 2,000 lines, the same error is harder to reason about.

While learning a new Zig feature, write a small test file first:

```text
experiment.zig
```

Run it with:

```bash
zig run experiment.zig
```

Once you understand the feature, move it into your real project.

#### Use `zig fmt`

Sometimes formatting helps reveal mistakes.

Run:

```bash
zig fmt main.zig
```

If the code has a syntax error, the formatter may fail. That is useful information.

If formatting succeeds, the code becomes easier to read.

Clean formatting makes missing braces, nested blocks, and indentation problems easier to see.

#### A Calm Debugging Routine

When Zig gives an error, use this routine:

| Step | Action |
|---|---|
| 1 | Read the first error |
| 2 | Find the file, line, and column |
| 3 | Read the error text slowly |
| 4 | Check the line before the marked line |
| 5 | Fix one thing |
| 6 | Run the command again |

Do not change ten things at once. That makes it harder to know which change fixed the problem.

#### What You Should Remember

Zig error messages are part of the learning process.

The compiler points you to the file, line, column, and kind of problem.

Start with the first error. Check the nearby code. Fix one issue. Compile again.

Over time, you will start to recognize common errors quickly: missing semicolons, wrong types, unknown names, unused values, bad format strings, missing imports, and unhandled errors.

