go-delve/delve · warning

unreadable tophash: %v

Error message

unreadable tophash: %v

What it means

While iterating a Go map during variable evaluation, the iterator reads each bucket's tophash byte. If that memory cannot be read (asUint fails, typically because the backing memory is unreadable), the resulting Variable is marked Unreadable with this error instead of continuing the iteration.

Source

Thrown at pkg/proc/mapiter.go:259

		return false
	}

	return true
}

func (it *mapIteratorClassic) next() bool {
	for {
		if it.b == nil || it.idx >= it.tophashes.Len {
			r := it.nextBucket()
			if !r {
				return false
			}
			it.idx = 0
		}
		tophash, _ := it.tophashes.sliceAccess(int(it.idx))
		h, err := tophash.asUint()
		if err != nil {
			it.v.Unreadable = fmt.Errorf("unreadable tophash: %v", err)
			return false
		}
		it.idx++
		if h != hashTophashEmptyZero && h != it.hashTophashEmptyOne {
			return true
		}
	}
}

func (it *mapIteratorClassic) key() *Variable {
	k, _ := it.keys.sliceAccess(int(it.idx - 1))
	if k.Kind == reflect.Ptr && !it.keyTypeIsPtr {
		k = k.maybeDereference()
	}
	return k
}

func (it *mapIteratorClassic) value() *Variable {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Re-read/re-evaluate the map variable at the current program stop instead of using a cached Variable
  2. Verify the target process memory is intact (check for heap corruption) and the core file is complete
  3. Check delve/Go version compatibility: map internals differ between Go versions and old delve builds misread new runtimes

Example fix

// before
v, _ := debugger.FindVariable(...)
iterate(v) // uses stale v after map was modified
// after
v, err := debugger.FindVariable(...) // re-evaluate at current stop
if err != nil { return err }
if v.Unreadable != nil { return v.Unreadable }
iterate(v)
Defensive patterns

Strategy: fallback

Validate before calling

if v.Unreadable != nil {
    return fmt.Errorf("map not readable: %v", v.Unreadable)
}

Type guard

func isReadable(v *proc.Variable) bool {
    return v.Unreadable == nil
}

Try / catch

ok := iterateMap(it)
if !ok && it.v.Unreadable != nil {
    if strings.Contains(it.v.Unreadable.Error(), "unreadable tophash") {
        // re-evaluate the map at the current stop point
        return reEvaluateAndIterate(mapExpr)
    }
    return it.v.Unreadable
}

Prevention

When it happens

Trigger: Evaluating/printing a map variable whose bucket tophash bytes live in memory delve cannot read (stale pointers, freed/corrupted map memory, reading a map from a core dump with missing pages).

Common situations: Inspecting a map after the underlying allocation was moved or freed (e.g. stale Variable captured before a map grew), debugging corrupted heap state, or reading maps from truncated core files.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/a80ee7748513bd5f. Report an issue: GitHub.