containerd/containerd · error

failed to parse line %q: %w

Error message

failed to parse line %q: %w

What it means

Info() runs `dmsetup info` and parses each output line with fmt.Sscanf into an Info struct (name, major/minor, open/target counts, event number). This error means a line of dmsetup output did not match the expected field layout, so device info could not be produced.

Source

Thrown at plugins/snapshots/devmapper/dmsetup/dmsetup.go:261

	for i, line := range lines {
		var (
			attr = ""
			info = &DeviceInfo{}
		)

		_, err := fmt.Sscan(line,
			&info.Name,
			&info.BlockDeviceName,
			&attr,
			&info.Major,
			&info.Minor,
			&info.OpenCount,
			&info.TargetCount,
			&info.EventNumber)

		if err != nil {
			return nil, fmt.Errorf("failed to parse line %q: %w", line, err)
		}

		// Parse attributes (see "man 8 dmsetup" for details)
		info.Suspended = strings.Contains(attr, "s")
		info.ReadOnly = strings.Contains(attr, "r")
		info.TableLive = strings.Contains(attr, "L")
		info.TableInactive = strings.Contains(attr, "I")

		devices[i] = info
	}

	return devices, nil
}

// Version returns "dmsetup version" output
func Version() (string, error) {
	return dmsetup("version")
}

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Run `dmsetup info <device>` manually and compare output to the format string Info() expects.
  2. Ensure dmsetup (device-mapper package) is installed and at a compatible version.
  3. Check that only stdout is parsed — stderr noise should be captured separately by the exec helper.
  4. Inspect the wrapped %w cause to see which field conversion failed.
  5. Verify the kernel device-mapper module is loaded (lsmod | grep dm_mod).

Example fix

// before
cmd := exec.Command("dmsetup", "info") // wrong binary path prints shell error into output
// after
out, err := exec.Command("/usr/sbin/dmsetup", "info").Output()
if err != nil { return fmt.Errorf("dmsetup info: %w: %s", err, out) }
Defensive patterns

Strategy: try-catch

Validate before calling

func dmsetupAvailable() error {
    if _, err := exec.LookPath("dmsetup"); err != nil {
        return fmt.Errorf("dmsetup not installed: %w", err)
    }
    return nil
}

Try / catch

info, err := devInfo(name)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse line") {
        out, raw := exec.Command("dmsetup", "info").CombinedOutput()
        return fmt.Errorf("dmsetup info unparseable: %w; raw output: %s (%v)", err, raw, out)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Info, IsActivated, NewPoolDevice, or isInUse when dmsetup emits an unexpected line — e.g. an error/warning message, a localized or differently formatted line, or empty/garbage output from a mismatched dmsetup version.

Common situations: dmsetup not installed or wrong version producing different column formats; device-mapper kernel module issues causing dmsetup to print errors instead of info rows; parsing stderr mixed into stdout.

Understand the failure class

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/5399981b95626ff6. Report an issue: GitHub.