---
title: "attempt to unwrap null optional — Como Resolver em Zig"
url: "https://ziglang.com.br/erros/attempt-to-unwrap-null-optional-como-resolver-em-zig/"
markdown_url: "https://ziglang.com.br/erros/attempt-to-unwrap-null-optional-como-resolver-em-zig.MD"
description: "Entenda o erro 'attempt to unwrap null optional' em Zig, que ocorre ao tentar acessar o valor de um optional que é null. Veja soluções."
date: "2026-02-21"
author: "Zig Brasil"
---

# attempt to unwrap null optional — Como Resolver em Zig

Entenda o erro 'attempt to unwrap null optional' em Zig, que ocorre ao tentar acessar o valor de um optional que é null. Veja soluções.


# attempt to unwrap null optional — Como Resolver em Zig

## O Que Este Erro Significa

O erro `attempt to unwrap null optional` é um panic de runtime que ocorre quando você tenta acessar o valor interno de um tipo optional (`?T`) que é `null`. Em Zig, optionals são tipos que podem conter um valor do tipo `T` ou ser `null`. Tentar extrair o valor quando ele é `null` é um erro grave, similar ao `NullPointerException` em Java ou `nil` dereference em Go.

Esse panic geralmente acontece quando você usa `.?` (operador de unwrap) ou `orelse unreachable` em um optional que é `null`.

## Causas Comuns

### 1. Usar .? em Optional Null

```zig
pub fn main() void {
    const valor: ?u32 = null;
    const x = valor.?; // PANIC: attempt to unwrap null optional
    _ = x;
}
```

### 2. Função que Retorna null Inesperadamente

```zig
fn encontrar(arr: []const u32, alvo: u32) ?usize {
    for (arr, 0..) |item, i| {
        if (item == alvo) return i;
    }
    return null;
}

pub fn main() void {
    const arr = [_]u32{ 1, 2, 3 };
    const idx = encontrar(&arr, 99).?; // PANIC: 99 não está no array
    _ = idx;
}
```

### 3. Acessar Ponteiro Optional Null

```zig
pub fn main() void {
    var ptr: ?*u32 = null;
    ptr.?.* = 42; // PANIC: ponteiro optional é null
}
```

### 4. Cadeia de Optionals

```zig
const Config = struct {
    porta: ?u16,
};

fn carregarConfig() ?Config {
    return null;
}

pub fn main() void {
    const config = carregarConfig().?; // PANIC: config é null
    _ = config;
}
```

### 5. Optional em Struct Não Inicializado

```zig
const Usuario = struct {
    nome: []const u8,
    email: ?[]const u8 = null,
};

pub fn main() void {
    const user = Usuario{ .nome = "Ana" };
    const email = user.email.?; // PANIC: email não foi definido (é null)
    _ = email;
}
```

## Como Corrigir

### Solução 1: Usar orelse com Valor Padrão

A forma mais segura de lidar com optionals:

```zig
pub fn main() void {
    const valor: ?u32 = null;
    const x = valor orelse 0; // Se null, usa 0
    _ = x; // x == 0
}
```

### Solução 2: Usar if Para Verificar

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

pub fn main() void {
    const valor: ?u32 = null;
    if (valor) |v| {
        std.debug.print("valor: {}\n", .{v});
    } else {
        std.debug.print("valor é null\n", .{});
    }
}
```

### Solução 3: Usar orelse return/break/continue

```zig
fn processar(dados: ?[]const u8) void {
    const d = dados orelse return; // Retorna se null
    // Daqui em diante, 'd' é garantidamente não-null
    _ = d;
}
```

### Solução 4: Usar orelse com @panic Para Mensagem Customizada

Se o null realmente não deveria acontecer:

```zig
pub fn main() void {
    const config = carregarConfigObrigatoria();
    const porta = config.porta orelse @panic("Porta não configurada!");
    _ = porta;
}
```

### Solução 5: Verificar Antes de Desempacotar

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

fn encontrar(arr: []const u32, alvo: u32) ?usize {
    for (arr, 0..) |item, i| {
        if (item == alvo) return i;
    }
    return null;
}

pub fn main() void {
    const arr = [_]u32{ 1, 2, 3 };
    if (encontrar(&arr, 99)) |idx| {
        std.debug.print("Encontrado no índice: {}\n", .{idx});
    } else {
        std.debug.print("Não encontrado\n", .{});
    }
}
```

### Solução 6: Converter Optional em Error Union

```zig
const BuscaError = error{NaoEncontrado};

fn encontrarOuErro(arr: []const u32, alvo: u32) BuscaError!usize {
    for (arr, 0..) |item, i| {
        if (item == alvo) return i;
    }
    return BuscaError.NaoEncontrado;
}
```

## Padrões Seguros com Optionals

### Guard Clause com orelse return

```zig
fn processar(config: ?Config) !void {
    const cfg = config orelse return error.ConfigNula;
    // Usa cfg com segurança
    _ = cfg;
}
```

### Encadeamento Seguro

```zig
fn obterPorta(config: ?Config) u16 {
    const cfg = config orelse return 8080;
    const porta = cfg.porta orelse return 8080;
    return porta;
}
```

### Map/Transform Optional

```zig
fn formatarEmail(email: ?[]const u8) []const u8 {
    return email orelse "(sem email)";
}
```

## Quando .? É Aceitável

Use `.?` apenas quando você tem **certeza absoluta** de que o valor não é null:

```zig
fn processar(lista: []const ?u32) void {
    for (lista) |item| {
        if (item != null) {
            // Aqui sabemos que item não é null
            const valor = item.?; // Seguro neste contexto
            _ = valor;
        }
    }
}
```

Mas mesmo nesses casos, `if (item) |valor|` é mais idiomático.

## Erros Relacionados

- [attempt to unwrap error](/erros/erro-unwrap-error/) — Tentativa de desempacotar error union
- [error not handled](/erros/erro-error-not-handled/) — Erro não tratado
- [catch reached unreachable](/erros/erro-catch-unreachable/) — Catch atingiu unreachable

## Links Úteis

- [Documentação oficial do Zig — Optionals](https://ziglang.org/documentation/master/#Optionals)
- [Zig Language Reference — Optional Pointers](https://ziglang.org/documentation/master/#Optional-Pointers)
