go-delve/delve · error

unreadable length

Error message

unreadable length: %v

What it means

When loading a channel variable, Delve reads the 'qcount' field (structType.Field[1]) from the runtime hchan struct. If that memory load fails, the channel length cannot be determined and the whole channel variable is marked unreadable.

Solutions

  1. Print the channel variable itself rather than relying on its length; check chanBuf/base address validity first
  2. If using a core dump, verify the dump captured the heap region containing the channel (full-heap core, not filtered)
  3. Re-run the debug session; transient unreadable memory during a stopped process usually resolves on a fresh stop
  4. Check that the binary and core/debug info match (same build) so the hchan struct layout offsets are correct

Example fix

// before
print len(ch)            // unreadable length: location registers not available
// after: inspect the channel struct first and confirm validity
print ch                 // shows unreadable flag if memory is bad
printf("%d\n", ch.qcount) // only if ch readable
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the channel variable is readable before asking for len()
chVar, err := evalVariable("ch")
if err != nil || chVar.Unreadable != nil { /* fallback: print header manually */ }

Try / catch

if v, err := dbg.EvalVariable(scope, "ch", cfg); err != nil {
    // RPC-level failure
} else if v.Unreadable != nil {
    log.Printf("channel unreadable: %v", v.Unreadable) // covers 'unreadable length'
}

Prevention

When it happens

Trigger: Evaluating len(ch) or printing a channel variable where the hchan header memory is unreadable: the channel address is invalid, the buffer memory page is unmapped, or the target died mid-read.

Common situations: Inspecting channels in core dumps where the heap page containing the channel was not dumped; debugging a channel whose memory was freed/corrupted; evaluating a channel through a stale pointer after the program crashed.

Related errors


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

Appendix: source

Thrown at pkg/proc/variables.go:1695

		return
	}
	sv := v.clone()
	sv.RealType = godwarf.ResolveTypedef(&(chanType.TypedefType))
	sv = sv.maybeDereference()
	if sv.Unreadable != nil || sv.Addr == 0 {
		return
	}
	v.Base = sv.Addr
	structType, ok := sv.DwarfType.(*godwarf.StructType)
	if !ok {
		v.Unreadable = errors.New("bad channel type")
		return
	}

	lenAddr, _ := sv.toField(structType.Field[1])
	lenAddr.loadValue(loadSingleValue)
	if lenAddr.Unreadable != nil {
		v.Unreadable = fmt.Errorf("unreadable length: %v", lenAddr.Unreadable)
		return
	}
	chanLen, _ := constant.Uint64Val(lenAddr.Value)

	newStructType := &godwarf.StructType{}
	*newStructType = *structType
	newStructType.Field = make([]*godwarf.StructField, len(structType.Field))

	for i := range structType.Field {
		field := &godwarf.StructField{}
		*field = *structType.Field[i]
		if field.Name == "buf" {
			field.Type = pointerTo(fakeArrayType(chanLen, chanType.ElemType), v.bi.Arch)
		}
		newStructType.Field[i] = field
	}

	v.RealType = &godwarf.ChanType{

View on GitHub (pinned to a23773e6c3)