Fixing 'panic: assignment to entry in nil map' in Go

beginner🔷 Go2026-04-09| Go runtime (All versions), Linux/macOS/Windows

Error Message

panic: assignment to entry in nil map
#go#golang#debugging#runtime-error#maps

TL;DR: The Quick Fix

This crash occurs because you declared a map variable but never allocated memory for it. Go allows you to read from a nil map, but writing to one triggers an immediate panic.

The Wrong Way:

var counts map[string]int
counts["users"] = 10 // ❌ PANIC HERE

The Right Way (using make):

counts := make(map[string]int)
counts["users"] = 10 // ✅ Works

The Right Way (using a literal):

counts := map[string]int{}
counts["users"] = 10 // ✅ Works

Why Does This Happen?

Maps in Go are reference types. When you write var m map[K]V, the initial value of m is nil. It doesn't point to an initialized hash table yet.

Go is surprisingly lenient with nil maps during read operations. If you try to access a key in a nil map, Go simply returns the zero value for that type (like 0 for integers or "" for strings). However, the runtime draws a hard line at writes. It won't automatically allocate memory when you assign a value. Instead, it halts the program to prevent memory corruption.

Common Pitfalls and Solutions

1. The Uninitialized Global or Local Variable

This is the most common mistake. You define a map to track something—like HTTP response codes—but skip the initialization step.

func trackStatus() {
    var statusCodes map[int]string
    // ... logic happens
    statusCodes[200] = "OK" // Error: assignment to entry in nil map
}

The Fix: Always use make(). If you know you'll store roughly 100 items, you can even pre-allocate space with make(map[int]string, 100) to improve performance.

2. Maps Inside Structs

Initializing a struct does not automatically initialize any maps contained within it. This is a frequent source of bugs in larger applications.

type UserProfile struct {
    ID       int
    Settings map[string]string
}

func main() {
    u := UserProfile{ID: 1}
    u.Settings["theme"] = "dark" // ❌ PANIC: Settings is nil
}

The Fix: Use a constructor function. This pattern ensures your struct is always ready for use immediately after creation.

func NewUserProfile(id int) *UserProfile {
    return &UserProfile{
        ID:       id,
        Settings: make(map[string]string),
    }
}

3. Lazy Initialization for JSON

The encoding/json package is smart. If you unmarshal JSON data into a nil map, Go initializes it for you. But if the incoming JSON is empty or the unmarshaling fails, the map remains nil.

var data map[string]interface{}
// If json.Unmarshal isn't called or fails, data stays nil
err := json.Unmarshal(rawBytes, &data)

// Logic that assumes 'data' is ready will crash here
data["updated_at"] = time.Now().Unix() 

How to Verify and Prevent This

To keep your code stable, follow these three practical steps:

- **Run Static Analysis:** Tools like `go vet` or `golangci-lint` can often spot uninitialized maps before you even run your code.
- **Defensive Nil Checks:** If a function receives a map from an external source, check it. A simple `if m == nil { m = make(map[K]V) }` can save your production environment from a crash.
- **Unit Tests:** Write tests that simulate empty inputs. If your logic tries to write to an uninitialized map, the test will fail loudly.

Summary Table

Operation
Result on Nil Map


`val := m["key"]`
Safe (returns zero value)


`len(m)`
Safe (returns 0)


`delete(m, "key")`
Safe (does nothing)


`m["key"] = "val"`
**Panic (Crash)**

Related Error Notes