Quick answer
You indexed a slice/array out of bounds. The message is precise: [N] is the index you used, M is the length, so valid indexes are 0…M-1. Fix it with a length check (if i < len(s)), a correct loop bound (i < len(s), not <=), or append instead of index-assignment on a zero-length slice.
The exact error string
s := []int{10, 20, 30}
fmt.Println(s[3])
// panic: runtime error: index out of range [3] with length 3
goroutine 1 [running]:
main.main()
/app/main.go:7 +0x1d
How to read it
The two numbers are the whole diagnosis: [3] is the index you asked for, with length 3 is the slice's length — and the last valid index is always length − 1 (here, 2). So you went one past the end. The first main.* stack frame names the file:line; the slice indexed there is the culprit.
Cause 1: off-by-one loop
for i := 0; i <= len(s); i++ { // ❌ <= goes one past the end
fmt.Println(s[i])
}
for i := 0; i < len(s); i++ { // ✅ last index is len(s)-1
fmt.Println(s[i])
}
for i, v := range s { // ✅ best — range can't overflow
fmt.Println(i, v)
}
Cause 2: empty slice — [0] with length 0
first := results[0] // ❌ panics if results is empty
if len(results) > 0 { // ✅ guard
first := results[0]
}
Cause 3: index-assign on a zero-length slice
make([]T, 0, cap) has length 0 even with capacity reserved — you must append, not index-assign:
s := make([]int, 0, 10) // len 0, cap 10
s[0] = 1 // ❌ index out of range [0] with length 0
s = append(s, 1) // ✅ grows the slice
s := make([]int, 10) // ✅ or make with a real length, then index
s[0] = 1
Cause 4: trusting external/JSON data length
Indexing fixed positions of a parsed payload (parts[1], row[2]) panics when the input is shorter than you assumed — a common bug with split strings, CSV rows, or JSON arrays from an API:
parts := strings.Split(line, ",")
name := parts[1] // ❌ panics if the line had no comma
if len(parts) >= 2 { // ✅ validate shape before indexing
name := parts[1]
}
Common variants of this panic
| Message | Cause | Fix |
|---|---|---|
index out of range [N] with length M | index ≥ length | check i < len(s) |
index out of range [0] with length 0 | empty slice | if len(s) > 0 |
panic in a for loop | <= off-by-one | < len(s) or range |
panic on s[0]=x | zero-length slice | append or make([]T, n) |
slice bounds out of range [a:b] | bad slice expression | validate a, b vs len |
Debugging checklist
- ✓ Read
[N] with length M— valid indexes are0…M-1 - ✓ The first
main.*stack frame names the line - ✓ Loop uses
i < len(s)(not<=) — or userange - ✓ Possibly empty? Guard with
if len(s) > 0 - ✓ Growing a slice?
append, don't index-assign past the length - ✓ Indexing split/CSV/JSON data? Check the length first
Frequently Asked Questions
What does '[N] with length M' tell me?
N is the index you tried to access and M is the slice's length, so valid indexes are 0 to M-1. 'index out of range [3] with length 3' means you used index 3 on a 3-element slice (valid: 0,1,2). The numbers tell you exactly how far out of bounds you went.
Why does index out of range [0] with length 0 happen?
The slice is empty, so even index 0 is invalid. This is common when you access s[0] without checking, or read a result that came back empty. Guard with if len(s) > 0 before indexing, or handle the empty case explicitly.
How do I fix an off-by-one loop?
Use i < len(s), not i <= len(s) — the last valid index is len(s)-1. Better, range over the slice (for i, v := range s) which never goes out of bounds. Off-by-one in the loop condition is the most common cause of this panic.
Why does s[i] = x panic but append doesn't?
Index assignment requires the index to already exist; a make([]T, 0, cap) slice has length 0, so s[0]=x panics even though capacity is reserved. Use append(s, x) to grow the slice, or make([]T, n) with a real length if you intend to index by position.
Is this the same as 'slice bounds out of range'?
Related but distinct. 'index out of range' is a single bad index (s[i]); 'slice bounds out of range' comes from a bad slice expression (s[a:b] where a or b is invalid). Both are fixed by validating against len(s) before the operation.
How do I find where it panicked?
The first main.* frame in the goroutine stack names the file and line. Open it; the slice/array indexed on that line is the one out of bounds, and the [N] with length M values tell you the index and the actual length to reconcile.
More backend & language errors
Browse the full reference for Go, Node.js, Python, and database errors — exact message, cause, and fix.