hashicorp/packer · error

failed to parse OS detection output: %s

Error message

failed to parse OS detection output: %s

What it means

After the OS-detection command succeeds, detectRemoteOS parses its trimmed stdout. On non-WinRM targets it expects one or two whitespace-separated fields (OS type, optional architecture); if the output is empty or unparseable such that osType or osArch remains empty, the provisioner returns this error with the raw output for debugging. Typically it means the command produced no usable stdout despite exiting 0.

Source

Thrown at provisioner/hcp-sbom/provisioner.go:414

	// Parse output
	var osType, osArch string
	if connType == "winrm" {
		osType = "Windows"
		osArch = strings.ToLower(output) // AMD64, ARM64, etc.
	} else {
		parts := strings.Fields(output)
		if len(parts) >= 2 {
			osType = parts[0] // Linux, Darwin, FreeBSD, etc.
			osArch = parts[1] // x86_64, aarch64, etc.
		} else if len(parts) == 1 {
			// Some systems might only return one value
			osType = parts[0]
			osArch = "unknown"
		}
	}

	if osType == "" || osArch == "" {
		return "", "", fmt.Errorf("failed to parse OS detection output: %s", output)
	}

	// Store in generatedData for potential reuse
	generatedData["OSType"] = osType
	generatedData["OSArch"] = osArch

	return osType, osArch, nil
}

// getUserDestination determines and returns the destination path for the user SBOM file.
func (p *Provisioner) getUserDestination() (string, error) {
	dst := p.config.Destination

	// Check if the destination exists and determine its type
	info, err := os.Stat(dst)
	if err == nil {
		if info.IsDir() {
			// If the destination is a directory, create a temporary file inside it

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Run `uname -s -m` interactively on the guest with the same user and confirm two fields (e.g. `Linux x86_64`) are printed.
  2. Pre-set OSType/OSArch via the build's generated data (e.g. a datasource or builder exposing them) so detectRemoteOS short-circuits and never parses stdout.
  3. Check the Packer log line `OS detection output: ...` — it shows exactly what stdout was captured; fix whatever blanks it (shell profile echo redirections, aliases).
  4. Retry with a plain POSIX shell (ssh_username account with /bin/sh default) to rule out shell-init interference.
  5. If it reproduces on a known-good guest, report the communicator (plugin) version — stdout capture may be broken in that communicator.
Defensive patterns

Strategy: fallback

Validate before calling

// Verify manually what the provisioner will see:
// out=$(ssh user@host 'uname -s -m'); echo "[$out]"  # expect two fields, non-empty

Type guard

// Post-condition check before relying on parsed values
func validOSDetection(osType, osArch string) bool {
    return osType != "" && osArch != ""
}

Try / catch

osType, osArch, err := p.detectRemoteOS(ctx, ui, comm, generatedData)
if err != nil {
    ui.Warn("OS detection failed, defaulting to linux/amd64")
    osType, osArch = "Linux", "x86_64" // fallback
}

Prevention

When it happens

Trigger: `uname -s -m` exits 0 but prints nothing to the captured stdout (output redirected, stdout wiring lost, cmd.Wait returning before output is fully captured), or prints only whitespace; for WinRM, output that lowercases to an empty string.

Common situations: Custom/busybox shells emitting a login banner but no command output; a communicator adapter that drops RemoteCmd.Stdout; SELinux or sandboxing blocking output; guest with locale/encoding wrappers that swallow stdout; using an exotic communicator whose ExitStatus is 0 while no data was streamed.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/c75c8af320da4873. Report an issue: GitHub.