go-delve/delve · error · errMapBucketsNotStruct

malformed map type: buckets, oldbuckets or overflow field no

Error message

malformed map type: buckets, oldbuckets or overflow field not a struct

What it means

Delve's classic (pre-swiss-table) map iterator reads the runtime hmap/bucket structs directly, assuming each map internal type has well-formed fields. errMapBucketsNotStruct is returned by mapIterator and nextBucket when the 'buckets', 'oldbuckets' or 'overflow' field of the map's bucket struct is not a struct type, which means the loaded DWARF type information does not match the Go runtime layout Delve expects.

Source

Thrown at pkg/proc/mapiter.go:128

	keyTypeIsPtr, elemTypeIsPtr bool

	tophashes *Variable
	keys      *Variable
	values    *Variable
	overflow  *Variable

	maxNumBuckets uint64 // maximum number of buckets to scan

	idx int64

	hashTophashEmptyOne uint64 // Go 1.12 and later has two sentinel tophash values for an empty cell, this is the second one (the first one hashTophashEmptyZero, the same as Go 1.11 and earlier)
	hashMinTopHash      uint64 // minimum value of tophash for a cell that isn't either evacuated or empty
}

var (
	errMapBucketContentsNotArray        = errors.New("malformed map type: keys, values or tophash of a bucket is not an array")
	errMapBucketContentsInconsistentLen = errors.New("malformed map type: inconsistent array length in bucket")
	errMapBucketsNotStruct              = errors.New("malformed map type: buckets, oldbuckets or overflow field not a struct")
)

func (it *mapIteratorClassic) nextBucket() bool {
	if it.overflow != nil && it.overflow.Addr > 0 {
		it.b = it.overflow
	} else {
		it.b = nil

		if it.maxNumBuckets > 0 && it.bidx >= it.maxNumBuckets {
			return false
		}

		for it.bidx < it.numbuckets {
			it.b = it.buckets.clone()
			it.b.Addr += uint64(it.buckets.DwarfType.Size()) * it.bidx

			if it.oldbuckets.Addr <= 0 {
				break

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Upgrade Delve to the version matching the Go toolchain used to build the target binary
  2. Rebuild the target binary without flags that strip DWARF (remove -ldflags "-s -w" or -trimpath misuse)
  3. Check the Go version of the binary (go version <binary>) and the Delve version (dlv version) for compatibility

Example fix

// before
go build -ldflags="-s -w" main.go
dlv exec ./main
// after
go build -gcflags="all=-N -l" main.go
dlv exec ./main
Defensive patterns

Strategy: validation

Validate before calling

// In a delve support script or issue report, verify toolchain alignment first:
//   $ go version <target-binary>
//   $ dlv version
// Proceed only if the Go major.minor of the binary matches a Delve release known to support it.

Prevention

When it happens

Trigger: Evaluating or iterating a map whose bucket type parsed from DWARF has a non-struct buckets/oldbuckets/overflow field — e.g. calling 'print m' or a range expression on a map when the target binary's runtime type layout differs from what Delve expects (Go version mismatch, stripped or corrupted DWARF).

Common situations: Debugging a binary built with a much newer/older Go version than the map layout the Delve version supports; binaries with cgo or custom linkers producing unusual DWARF; attaching to processes built with trimmed debug info.

Understand the failure class

Related errors


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