---
title: "Catch Reached Unreachable — Como Resolver em Zig"
url: "https://ziglang.com.br/erros/catch-reached-unreachable-como-resolver-em-zig/"
markdown_url: "https://ziglang.com.br/erros/catch-reached-unreachable-como-resolver-em-zig.MD"
description: "Entenda o panic 'catch reached unreachable' em Zig, que ocorre quando catch unreachable encontra um erro real. Veja como diagnosticar e corrigir."
date: "2026-02-21"
author: "Zig Brasil"
---

# Catch Reached Unreachable — Como Resolver em Zig

Entenda o panic 'catch reached unreachable' em Zig, que ocorre quando catch unreachable encontra um erro real. Veja como diagnosticar e corrigir.


# Catch Reached Unreachable — Como Resolver em Zig

## O Que Este Erro Significa

O panic `reached unreachable` ocorre em runtime quando uma expressão `catch unreachable` encontra um erro real. O programador declarou ao compilador que aquela operação "nunca falhará", mas em tempo de execução ela falhou. Zig trata isso como uma violação de contrato e emite um panic imediato.

A mensagem típica:

```
thread 1 panic: reached unreachable
```

Esse padrão é similar a um `assert` que falhou. O `catch unreachable` é essencialmente uma promessa ao compilador de que o erro não acontecerá, e quando essa promessa é quebrada, o programa encerra.

## Causas Comuns

### 1. Presunção Incorreta de que Função Não Falhará

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

pub fn main() void {
    // PANIC: arquivo pode não existir!
    const file = std.fs.cwd().openFile("config.txt", .{}) catch unreachable;
    defer file.close();
    _ = file;
}
```

### 2. Alocação que Pode Falhar

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

pub fn main() void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    // PANIC: alocação PODE falhar com OutOfMemory
    const dados = allocator.alloc(u8, 1_000_000) catch unreachable;
    _ = dados;
}
```

### 3. Parsing com Input Não Validado

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

pub fn main() void {
    const input = "nao_e_numero";
    // PANIC: input não é um número válido
    const numero = std.fmt.parseInt(i32, input, 10) catch unreachable;
    _ = numero;
}
```

### 4. Conversão de Tipo que Pode Falhar

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

pub fn main() void {
    const valor: i32 = -1;
    // PANIC: não pode converter -1 para u32
    const positivo = std.math.cast(u32, valor) orelse unreachable;
    _ = positivo;
}
```

### 5. Operação de I/O Sem Garantia

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

pub fn main() void {
    const stdout = std.io.getStdOut().writer();
    // PANIC: escrita pode falhar (pipe quebrado, disco cheio, etc.)
    stdout.print("Olá mundo\n", .{}) catch unreachable;
}
```

## Como Corrigir

### Solucao 1: Usar try ao Invés de catch unreachable

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

pub fn main() !void {
    const file = try std.fs.cwd().openFile("config.txt", .{});
    defer file.close();
    // Erro é propagado para o chamador
}
```

### Solucao 2: Tratar o Erro com catch

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

pub fn main() void {
    const file = std.fs.cwd().openFile("config.txt", .{}) catch |err| {
        std.debug.print("Não foi possível abrir config: {}\n", .{err});
        return;
    };
    defer file.close();
    _ = file;
}
```

### Solucao 3: Usar catch com Valor Padrão

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

pub fn main() void {
    const input = "nao_e_numero";
    const numero = std.fmt.parseInt(i32, input, 10) catch 0;
    std.debug.print("Número: {}\n", .{numero});
}
```

### Solucao 4: Validar Antes de Usar unreachable

Se você realmente precisa de unreachable, valide as condições primeiro:

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

pub fn main() void {
    const input = "42";

    // Valida primeiro
    for (input) |c| {
        if (c < '0' or c > '9') {
            std.debug.print("Input inválido\n", .{});
            return;
        }
    }

    // Agora é seguro usar catch unreachable (input validado)
    const numero = std.fmt.parseInt(i32, input, 10) catch unreachable;
    std.debug.print("Número: {}\n", .{numero});
}
```

### Solucao 5: Usar @panic com Mensagem Customizada

Se o erro realmente não deveria acontecer, ao menos dê uma mensagem clara:

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

pub fn main() void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const dados = allocator.alloc(u8, 64) catch {
        @panic("Falha crítica: não foi possível alocar 64 bytes");
    };
    _ = dados;
}
```

### Solucao 6: Usar if com Error Union

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

pub fn main() void {
    if (std.fs.cwd().openFile("config.txt", .{})) |file| {
        defer file.close();
        std.debug.print("Arquivo aberto com sucesso\n", .{});
    } else |err| {
        std.debug.print("Erro: {}\n", .{err});
    }
}
```

## Quando catch unreachable É Aceitável

O `catch unreachable` é justificado apenas em situações onde o erro é matematicamente impossível:

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

pub fn main() void {
    // bufPrint com buffer grande o suficiente e formato fixo
    // NÃO pode falhar — o buffer é definitivamente grande o suficiente
    var buf: [100]u8 = undefined;
    const texto = std.fmt.bufPrint(&buf, "valor: {d}", .{@as(u32, 42)}) catch unreachable;
    std.debug.print("{s}\n", .{texto});
}

fn somaSegura(a: u7, b: u7) u8 {
    // u7 max = 127, portanto 127 + 127 = 254 < 256 (max u8)
    // Essa adição NUNCA pode falhar com overflow em u8
    return std.math.add(u8, a, b) catch unreachable;
}
```

## Diferenca entre catch unreachable e orelse unreachable

```zig
// catch unreachable — para error unions (!T)
const valor = funcaoQuePodeFalhar() catch unreachable;

// orelse unreachable — para optionals (?T)
const valor2 = funcaoQueRetornaOptional() orelse unreachable;

// Ambos causam panic se a condição ocorrer
// Ambos devem ser usados com extremo cuidado
```

## Dica: Prefira Falhar Graciosamente

Em vez de `catch unreachable`, considere sempre se existe um caminho de recuperação:

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

// RUIM: catch unreachable em alocação
fn criarBufferRuim(allocator: std.mem.Allocator) []u8 {
    return allocator.alloc(u8, 1024) catch unreachable;
}

// BOM: propagar erro
fn criarBufferBom(allocator: std.mem.Allocator) ![]u8 {
    return allocator.alloc(u8, 1024);
}
```

## Erros Relacionados

- [Unreachable code](/erros/erro-unreachable-code/) — Código inalcançável detectado pelo compilador
- [Error not handled](/erros/erro-error-not-handled/) — Erro não tratado
- [Try in non-error function](/erros/erro-try-in-non-error-fn/) — Try em função sem retorno de erro
- [Attempt to unwrap error](/erros/erro-unwrap-error/) — Tentativa de desempacotar error

## Links Úteis

- [Documentação oficial do Zig — unreachable](https://ziglang.org/documentation/master/#unreachable)
- [Documentação oficial do Zig — Error Handling](https://ziglang.org/documentation/master/#Errors)
- [Receitas de tratamento de erros](/receitas/)
- [Tutorial sobre error unions e optionals](/tutoriais/)
