# `@panic`

### `@panic`

`@panic` stops the program immediately with a message.

It is used when the program reaches a state that should never happen, or when continuing would be unsafe.

```zig
@panic("something went wrong");
```

This tells Zig:

```text
Stop the program here.
Print this message.
```

#### A Simple Example

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

pub fn main() void {
    @panic("this program cannot continue");

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

The second print does not run. The program stops at `@panic`.

#### Panic Means Program Failure

A panic is not normal error handling.

Use errors for expected failure:

```zig
fn openConfig() !void {
    return error.FileNotFound;
}
```

Use panic for programmer mistakes or impossible states:

```zig
fn getModeName(mode: u8) []const u8 {
    return switch (mode) {
        0 => "read",
        1 => "write",
        2 => "execute",
        else => @panic("invalid mode"),
    };
}
```

Here, the code assumes only `0`, `1`, and `2` are valid modes. If another value appears, the program is already in a bad state.

#### Prefer Errors for Recoverable Problems

This is usually bad API design:

```zig
fn parseNumber(text: []const u8) u32 {
    if (text.len == 0) {
        @panic("empty input");
    }

    return 0;
}
```

Empty input is not impossible. It is a normal user input case.

A better version returns an error:

```zig
fn parseNumber(text: []const u8) !u32 {
    if (text.len == 0) {
        return error.EmptyInput;
    }

    return 0;
}
```

Now the caller can handle the failure.

#### Panic Is Useful for Broken Assumptions

A panic is reasonable when an internal invariant is broken.

```zig
const Stack = struct {
    items: [16]u8,
    len: usize,

    fn pop(self: *Stack) u8 {
        if (self.len == 0) {
            @panic("pop from empty stack");
        }

        self.len -= 1;
        return self.items[self.len];
    }
};
```

This version treats popping from an empty stack as a programmer error.

A safer public API would return an optional or an error:

```zig
fn pop(self: *Stack) ?u8 {
    if (self.len == 0) return null;

    self.len -= 1;
    return self.items[self.len];
}
```

#### `@panic` Does Not Return

After `@panic`, normal control flow ends.

This is why it can be used in places where a value is expected:

```zig
fn name(id: u8) []const u8 {
    return switch (id) {
        1 => "one",
        2 => "two",
        else => @panic("unknown id"),
    };
}
```

The function returns `[]const u8`.

The `else` branch does not return a string. It stops the program. Because it never returns, Zig can accept it in a value-producing expression.

#### Panic Message

The panic message should explain the failed assumption.

Poor message:

```zig
@panic("bad");
```

Better message:

```zig
@panic("expected non-empty stack");
```

The goal is to help the programmer find the bug quickly.

#### `@panic` vs `unreachable`

Use `@panic` when you want an explicit runtime failure with a message.

Use `unreachable` when you are telling Zig that a code path cannot happen.

```zig
else => unreachable,
```

`unreachable` is a stronger claim. It says the path is impossible. In safe modes, reaching it causes a safety panic. In optimized unsafe modes, the compiler may assume it never happens and optimize based on that assumption.

For beginner code, prefer `@panic` when you want a clear message.

#### Key Idea

`@panic(message)` stops the program.

Use it for impossible states, broken internal assumptions, and unrecoverable programmer errors.

Do not use it for normal failure that the caller should handle. Use Zig errors or optionals for those cases.

