hashicorp/nomad · error

error parsing fingerprint output as json: %w

Error message

error parsing fingerprint output as json: %w

What it means

After the fingerprint command runs successfully, Fingerprint unmarshals the plugin's stdout JSON into a PluginFingerprint struct. If the output is not valid JSON (or not shaped as expected), Nomad wraps the json.Unmarshal error with this message, logs it, and returns it. It indicates the external plugin violated the fingerprint output contract rather than an infrastructure failure.

Source

Thrown at client/hostvolumemanager/host_volume_plugin.go:299

// Must complete within 5 seconds
func (p *HostVolumePluginExternal) Fingerprint(ctx context.Context) (*PluginFingerprint, error) {
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()
	cmd := exec.CommandContext(ctx, p.Executable, "fingerprint")
	cmd.Env = []string{EnvOperation + "=fingerprint"}
	stdout, stderr, err := runCommand(cmd)
	log := p.log.With(
		"operation", "fingerprint",
		"stdout", string(stdout),
		"stderr", string(stderr),
	)
	if err != nil {
		log.Error("error running plugin", "error", err)
		return nil, fmt.Errorf("error fingerprinting plugin %q: %w", p.ID, err)
	}
	fprint := &PluginFingerprint{}
	if err := json.Unmarshal(stdout, fprint); err != nil {
		err = fmt.Errorf("error parsing fingerprint output as json: %w", err)
		log.Error("error parsing plugin output", "error", err)
		return nil, err
	}
	return fprint, nil
}

// Create calls the executable with the following parameters:
// arguments: $1=create
// environment:
// - DHV_OPERATION=create
// - DHV_VOLUMES_DIR={directory to put the volume in}
// - DHV_PLUGIN_DIR={path to directory containing plugins}
// - DHV_NAMESPACE={volume namespace}
// - DHV_VOLUME_NAME={name from the volume specification}
// - DHV_VOLUME_ID={volume ID generated by Nomad}
// - DHV_NODE_ID={Nomad node ID}
// - DHV_NODE_POOL={Nomad node pool}
// - DHV_CAPACITY_MIN_BYTES={capacity_min from the volume spec, expressed in bytes}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Run the plugin manually with fingerprint and inspect stdout; ensure it prints exactly one valid JSON document and sends all logs to stderr.
  2. Validate the JSON structure against the PluginFingerprint schema (expected fields and types) and fix the plugin's output.
  3. Check for empty stdout — usually the plugin crashed before printing; address the underlying crash first.
  4. Upgrade or downgrade the plugin binary to a version compatible with the Nomad client's expected fingerprint schema.

Example fix

// before: plugin contaminates stdout
fmt.Println("starting fingerprint...")
fmt.Println(`{"operations": {"create": true}}`)

// after
fmt.Fprintln(os.Stderr, "starting fingerprint...")
fmt.Println(`{"operations": {"create": true}}`)
Defensive patterns

Strategy: validation

Validate before calling

func validateFingerprintOutput(stdout []byte) error {
    trimmed := bytes.TrimPrefix(bytes.TrimSpace(stdout), []byte("\xef\xbb\xbf")) // strip BOM
    if len(trimmed) == 0 {
        return fmt.Errorf("plugin produced empty fingerprint output")
    }
    var fprint PluginFingerprint
    if err := json.Unmarshal(trimmed, &fprint); err != nil {
        return fmt.Errorf("plugin stdout is not valid fingerprint JSON: %w; output: %.200q", err, trimmed)
    }
    return nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "error parsing fingerprint output as json") {
    var jsonErr *json.UnmarshalTypeError
    if errors.As(err, &jsonErr) {
        log.Error("fingerprint field type mismatch", "field", jsonErr.Field)
    } else {
        log.Error("plugin stdout contaminated; ensure logs go to stderr", "err", err)
    }
}

Prevention

When it happens

Trigger: Calling Fingerprint where the plugin printed non-JSON output: human-readable log lines on stdout, empty output, exit-message strings, or JSON fields whose types don't match PluginFingerprint (e.g. string where a number is expected).

Common situations: Plugin writes debug/logging output to stdout instead of stderr, contaminating the JSON; plugin returns empty output on early exit; plugin emits JSON with a BOM or trailing text; a plugin version emits a schema the Nomad client can't unmarshal.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/3dc5f1c3ba8f5d63. Report an issue: GitHub.