# Appendix C. Common Compiler Errors

## Appendix C. Common Compiler Errors

One of Zig’s strengths is compiler diagnostics. Zig tries to explain problems precisely instead of silently accepting dangerous behavior.

At first, Zig error messages can feel strict. That is normal. The compiler is teaching you how Zig thinks about types, memory, errors, and control flow.

This appendix explains common errors beginners see, why they happen, and how to fix them.

### C.1 “unused local constant”

Example:

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

Error:

```text
error: unused local constant
```

Zig does not allow unused variables by default.

Why?

Unused variables often mean:

- forgotten code
- incomplete logic
- debugging leftovers
- bugs

Fix it by using the variable:

```zig
std.debug.print("{}\n", .{x});
```

Or discard it explicitly:

```zig
_ = x;
```

The `_` means “I intentionally ignore this value.”

### C.2 “unused function parameter”

Example:

```zig
fn add(a: i32, b: i32) i32 {
    return a;
}
```

Error:

```text
error: unused function parameter
```

You declared `b` but never used it.

Fix:

```zig
fn add(a: i32, _: i32) i32 {
    return a;
}
```

Using `_` says the parameter is intentionally unused.

### C.3 “expected type”

Example:

```zig
const x: i32 = "hello";
```

Error:

```text
error: expected type 'i32'
```

You tried to store a string in an integer variable.

Fix the type:

```zig
const x: []const u8 = "hello";
```

Or fix the value:

```zig
const x: i32 = 123;
```

### C.4 “expected type ‘usize’”

Example:

```zig
const nums = [_]i32{ 1, 2, 3 };

const x = nums[-1];
```

Array indexes use `usize`, which is an unsigned integer type.

Negative indexes are invalid.

Fix:

```zig
const x = nums[0];
```

### C.5 “integer overflow”

Example:

```zig
const x: u8 = 255;
const y = x + 1;
```

In safe build modes, Zig checks integer overflow.

A `u8` can only hold values from `0` to `255`.

Fix it by using a larger type:

```zig
const x: u16 = 255;
const y = x + 1;
```

Or use wrapping operators if overflow is intentional:

```zig
const y = x +% 1;
```

`+%` means wrapping addition.

### C.6 “division by zero”

Example:

```zig
const x = 10 / 0;
```

Error:

```text
error: division by zero
```

Zig checks this at compile time when possible.

Fix:

```zig
const x = 10 / 2;
```

Or validate runtime input before division.

### C.7 “index out of bounds”

Example:

```zig
const nums = [_]i32{ 10, 20, 30 };

const x = nums[10];
```

The array has only 3 items.

Valid indexes are:

| Index | Value |
|---|---|
| `0` | `10` |
| `1` | `20` |
| `2` | `30` |

Fix:

```zig
const x = nums[2];
```

### C.8 “unable to resolve comptime value”

Example:

```zig
var x: i32 = 10;

const y = comptime x;
```

`comptime` values must be known during compilation.

A runtime variable is not known at compile time.

Fix:

```zig
const x: i32 = 10;

const y = comptime x;
```

Or remove `comptime`.

### C.9 “value with comptime-only type”

Example:

```zig
const T = i32;

var x = T;
```

Types exist only at compile time.

You cannot store a type as a normal runtime value.

Usually you meant:

```zig
var x: T = 10;
```

### C.10 “error is ignored”

Example:

```zig
fn fail() !void {
    return error.BadThing;
}

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

Error:

```text
error: error is ignored
```

Zig requires explicit error handling.

Fix with `try`:

```zig
try fail();
```

Or `catch`:

```zig
fail() catch {};
```

### C.11 “expected optional type”

Example:

```zig
const x: i32 = null;
```

`null` only works with optional types.

Fix:

```zig
const x: ?i32 = null;
```

Optional types use `?`.

### C.12 “attempt to use null value”

Example:

```zig
var maybe: ?i32 = null;

const x = maybe.?;
```

`.?` unwraps an optional.

But `maybe` is `null`.

Fix:

```zig
if (maybe) |value| {
    std.debug.print("{}\n", .{value});
}
```

Or assign a real value first.

### C.13 “expected error union type”

Example:

```zig
const x: i32 = 10;

try x;
```

`try` only works with error unions like:

```zig
!i32
```

Fix:

```zig
const x = try loadValue();
```

Where `loadValue` returns an error union.

### C.14 “cannot dereference non-pointer type”

Example:

```zig
var x: i32 = 10;

x.* = 20;
```

`.*` only works on pointers.

Fix:

```zig
var x: i32 = 10;
var p = &x;

p.* = 20;
```

### C.15 “cannot assign to constant”

Example:

```zig
const x = 10;

x = 20;
```

`const` values cannot change.

Fix:

```zig
var x = 10;

x = 20;
```

### C.16 “missing semicolon”

Example:

```zig
const x = 10
const y = 20;
```

Zig statements usually end with `;`.

Fix:

```zig
const x = 10;
const y = 20;
```

### C.17 “expected statement, found ‘else’”

Example:

```zig
if (true)
    std.debug.print("yes\n", .{});
else
    std.debug.print("no\n", .{});
```

This can happen when formatting or structure is incorrect.

Usually braces fix it clearly:

```zig
if (true) {
    std.debug.print("yes\n", .{});
} else {
    std.debug.print("no\n", .{});
}
```

### C.18 “switch must handle all possibilities”

Example:

```zig
const dir = enum {
    north,
    south,
};

switch (dir) {
    .north => {},
}
```

You forgot `.south`.

Fix:

```zig
switch (dir) {
    .north => {},
    .south => {},
}
```

Or add `else`.

### C.19 “unreachable code”

Example:

```zig
return;

std.debug.print("hello\n", .{});
```

Code after `return` cannot run.

Fix by removing unreachable code.

### C.20 “unable to evaluate constant expression”

Example:

```zig
var x: i32 = 10;

const y = x + 1;
```

This may happen when Zig expects compile-time evaluation but sees runtime state.

Common causes:

- runtime variables in compile-time contexts
- runtime loops in type construction
- runtime allocation during compile-time execution

Fix by separating compile-time and runtime logic.

### C.21 “no field named”

Example:

```zig
const Point = struct {
    x: i32,
    y: i32,
};

const p = Point{
    .x = 1,
    .z = 2,
};
```

`Point` has no field named `z`.

Fix:

```zig
const p = Point{
    .x = 1,
    .y = 2,
};
```

### C.22 “no member named”

Example:

```zig
std.math.fakeFunction();
```

The function does not exist.

Possible causes:

- typo
- old documentation
- version mismatch
- removed API

Fix by checking:

- Zig version
- official documentation
- autocomplete/LSP suggestions

### C.23 “dependency loop detected”

Example:

```zig
const A = B;
const B = A;
```

The compiler cannot determine which declaration comes first.

Real dependency loops are usually more complex and involve:

- structs
- comptime logic
- imports
- default field values

Fix by restructuring dependencies.

### C.24 “local variable is never mutated”

Example:

```zig
var x = 10;
```

But `x` never changes.

Zig suggests using `const`.

Fix:

```zig
const x = 10;
```

This helps make programs clearer and safer.

### C.25 “expected ‘,’ after argument”

Example:

```zig
add(1 2);
```

Arguments are separated with commas.

Fix:

```zig
add(1, 2);
```

### C.26 “root struct has no member named ‘main’”

Example:

```zig
fn start() void {}
```

Zig executable programs need:

```zig
pub fn main() void {}
```

Fix by defining `main`.

### C.27 “C import failed”

Example:

```zig
const c = @cImport({
    @cInclude("missing.h");
});
```

Possible causes:

- header not installed
- include path missing
- library not installed

Fix by installing the dependency or adding include paths.

### C.28 “unable to find zig installation directory”

This usually means the Zig executable was moved incorrectly or installed incompletely.

Fixes:

- reinstall Zig
- use the official release archive
- avoid moving internal Zig files separately

### C.29 “Segmentation fault at address”

This is a runtime crash, not a compile error.

Common causes:

| Cause | Example |
|---|---|
| Null pointer | Dereferencing `null` |
| Invalid pointer | Using freed memory |
| Out-of-bounds access | Bad indexing |
| Uninitialized memory | Reading `undefined` |

Debug build modes help catch these problems earlier.

### C.30 Read Errors Carefully

A beginner mistake is reading only the first line of the error.

Zig errors often contain:

- the main error
- notes
- referenced declarations
- source locations
- type information
- dependency chains

Example structure:

```text
error: expected type 'i32'
note: found type '[]const u8'
note: called from here
```

The notes are important.

### C.31 A Good Debugging Process

When Zig reports an error:

1. Read the full message.
2. Find the exact line.
3. Identify the types involved.
4. Ask: compile-time or runtime?
5. Ask: pointer, optional, or error union?
6. Reduce the code to a tiny example.
7. Fix one error at a time.

Do not panic if the compiler prints many errors. One incorrect type can cause a chain of secondary errors.

### C.32 The Compiler Is Teaching You

Zig’s compiler is strict because Zig wants programs to be explicit.

Many beginner frustrations come from hidden assumptions:

- “I thought this could be null.”
- “I thought this would convert automatically.”
- “I thought this could fail silently.”
- “I thought this was mutable.”
- “I thought this happened at runtime.”

Zig tries to remove those hidden assumptions from the language.

That strictness is one reason Zig programs become easier to reason about as they grow.

