cloudflare/cloudflared · error

error retrieving output from command '%s': %w

Error message

error retrieving output from command '%s': %w

What it means

collectMemoryInformation runs 'cat /proc/meminfo' and parses its output to build memory diagnostics. If command.Output() returns an error (non-zero exit, missing binary, I/O failure), this wrapped error including the command string is returned. On Linux this usually means /proc/meminfo is unreadable or the environment lacks cat.

Source

Thrown at diagnostic/system_collector_linux.go:109

	)

	return info, gerror
}

func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
	// This function relies on the output of `cat /proc/meminfo` to retrieve
	// memoryMax and  memoryCurrent.
	// The expected output is in the format of `KEY VALUE UNIT`.
	const (
		memTotalPrefix     = "MemTotal"
		memAvailablePrefix = "MemAvailable"
	)

	command := exec.CommandContext(ctx, "cat", "/proc/meminfo")

	stdout, err := command.Output()
	if err != nil {
		return nil, "", fmt.Errorf("error retrieving output from command '%s': %w", command.String(), err)
	}

	output := string(stdout)

	mapper := func(field string) (uint64, error) {
		field = strings.TrimRight(field, " kB")

		return strconv.ParseUint(field, 10, 64)
	}

	memoryInfo, err := ParseMemoryInformationFromKV(output, memTotalPrefix, memAvailablePrefix, mapper)
	if err != nil {
		return nil, output, err
	}

	// returning raw output in case other collected information
	// resulted in errors
	return memoryInfo, output, nil

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Verify the file is readable: cat /proc/meminfo, as the same user running cloudflared.
  2. Check that /proc is mounted and not fully masked in the container (--cap-add / volume mounts for /proc).
  3. Ensure 'cat' exists in the image PATH (install coreutils/busybox).
  4. Inspect the wrapped exec error: exit status vs exec.ErrNotFound vs permission error to target the fix.

Example fix

// before
# gVisor sandbox: cat /proc/meminfo -> no such file
// after
# run with procfs available or capture:
var ee *exec.ExitError
if errors.As(err, &ee) { log stderr from ee.Stderr }
var nf *exec.Error
if errors.As(err, &nf) { /* cat missing: install coreutils */ }
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.ReadFile("/proc/meminfo"); err != nil {
	return fmt.Errorf("/proc/meminfo unreadable: %w", err)
}
if _, err := exec.LookPath("cat"); err != nil {
	return fmt.Errorf("cat missing: %w", err)
}

Try / catch

mem, _, err := systemCollect(ctx)
var nf *exec.Error
if errors.As(err, &nf) {
	// cat not found: install coreutils
} else if errors.As(err, &new(fs.PathError)) || strings.Contains(err.Error(), "/proc/meminfo") {
	// procfs unavailable/masked
}

Prevention

When it happens

Trigger: Collect called on Linux when /proc/meminfo cannot be read (procfs not mounted, e.g. some restricted containers/VMs), 'cat' is absent from PATH, or a seccomp/LSM policy denies the read.

Common situations: Hardened containers with masked /proc; minimal images without coreutils; sandboxed runtimes (gVisor etc.) with restricted procfs; compromised/oversized host where fd limits prevent spawning processes.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/f6043a661fd53776. Report an issue: GitHub.