go-delve/delve · error

malformed /proc/pid/maps on line %d: %q (wrong number of fie

Error message

malformed /proc/pid/maps on line %d: %q (wrong number of fields)

What it means

parseSmapsHeaderLine (pkg/proc/native/dump_linux.go), used by MemoryMap when building a Linux core dump, splits each /proc/pid/maps header line into at most 6 space-separated fields. The line did not yield exactly 6 fields, so it is not a valid maps entry and core dump generation aborts.

Source

Thrown at pkg/proc/native/dump_linux.go:84

			Addr: start,
			Size: end - start,

			Read:  perm[0] == 'r',
			Write: perm[1] == 'w',
			Exec:  perm[2] == 'x',

			Filename: filename,
			Offset:   offset,
		})

	}
	return r, nil
}

func parseSmapsHeaderLine(lineno int, in string) (start, end uint64, perm string, offset uint64, dev, filename string, err error) {
	fields := strings.SplitN(in, " ", 6)
	if len(fields) != 6 {
		err = fmt.Errorf("malformed /proc/pid/maps on line %d: %q (wrong number of fields)", lineno, in)
		return
	}

	v := strings.Split(fields[0], "-")
	if len(v) != 2 {
		err = fmt.Errorf("malformed /proc/pid/maps on line %d: %q (bad first field)", lineno, in)
		return
	}
	start, err = strconv.ParseUint(v[0], 16, 64)
	if err != nil {
		err = fmt.Errorf("malformed /proc/pid/maps on line %d: %q (%v)", lineno, in, err)
		return
	}
	end, err = strconv.ParseUint(v[1], 16, 64)
	if err != nil {
		err = fmt.Errorf("malformed /proc/pid/maps on line %d: %q (%v)", lineno, in, err)
		return
	}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Verify the process is reading /proc/<pid>/maps (not smaps or another pseudo-file).
  2. Check the kernel/sandbox: run under a standard kernel or gVisor-free environment and retry.
  3. Read the file atomically in one pass to avoid a truncated read; retry core dump creation.
  4. If a sandbox rewrites maps lines, dump memory map manually and create the core with an alternative tool.

Example fix

// before
f, _ := os.Open(fmt.Sprintf("/proc/%d/smaps", pid))
// after
f, _ := os.Open(fmt.Sprintf("/proc/%d/maps", pid))
Defensive patterns

Strategy: validation

Validate before calling

// Validate maps lines before parsing
count := len(strings.SplitN(line, " ", 7))
if count < 6 { return fmt.Errorf("skipping non-maps line: %q", line) }

Type guard

func isMapsHeaderLine(line string) bool {
    return len(strings.SplitN(strings.TrimSpace(line), " ", 7)) == 6 && strings.Contains(strings.Fields(line)[0], "-")
}

Try / catch

mm, err := MemoryMapFile(f)
if err != nil && strings.Contains(err.Error(), "wrong number of fields") {
    // fall back: re-read /proc/<pid>/maps fresh and retry once
    f2, _ := os.Open(fmt.Sprintf("/proc/%d/maps", pid)); mm, err = MemoryMapFile(f2)
}

Prevention

When it happens

Trigger: MemoryMap reading a /proc/<pid>/maps (or smaps) file whose header line lacks the standard 'start-end perms offset dev inode [path]' layout — e.g. reading /proc/self/smaps sections, a kernel with different formatting, or reading the wrong file.

Common situations: Very unusual kernels or LXC/gVisor sandboxes that alter /proc/pid/maps output; accidentally pointing the parser at smaps instead of maps; race where the file is truncated mid-read; intercepted /proc via FUSE.

Understand the failure class

Related errors


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