hashicorp/nomad · error

error marshaling volume pramaters: %w

Error message

error marshaling volume pramaters: %w

What it means

This error is returned by HostVolumePluginExternal.Create when the host volume plugin fails to JSON-marshal the request's Parameters map before invoking the external plugin executable. The comment notes it 'should never happen' since Parameters is a simple map[string]string, so it indicates the map contains a value that the encoding/json package cannot serialize (or a corrupted request). It wraps the underlying json.Marshal error via %w.

Source

Thrown at client/hostvolumemanager/host_volume_plugin.go:334

// - DHV_NODE_POOL={Nomad node pool}
// - DHV_CAPACITY_MIN_BYTES={capacity_min from the volume spec, expressed in bytes}
// - DHV_CAPACITY_MAX_BYTES={capacity_max from the volume spec, expressed in bytes}
// - DHV_PARAMETERS={stringified json of parameters from the volume spec}
//
// Response should be valid JSON on stdout with "path" and "bytes", e.g.:
// {"path": "/path/that/was/created", "bytes": 50000000}
// "path" must be provided to confirm the requested path is what was
// created by the plugin. "bytes" is the actual size of the volume created
// by the plugin; if excluded, it will default to 0.
//
// Must complete within 60 seconds (timeout on RPC)
func (p *HostVolumePluginExternal) Create(ctx context.Context,
	req *cstructs.ClientHostVolumeCreateRequest) (*HostVolumePluginCreateResponse, error) {

	params, err := json.Marshal(req.Parameters)
	if err != nil {
		// should never happen; req.Parameters is a simple map[string]string
		return nil, fmt.Errorf("error marshaling volume pramaters: %w", err)
	}
	envVars := []string{
		fmt.Sprintf("%s=%s", EnvOperation, "create"),
		fmt.Sprintf("%s=%s", EnvVolumesDir, p.VolumesDir),
		fmt.Sprintf("%s=%s", EnvPluginDir, p.PluginDir),
		fmt.Sprintf("%s=%s", EnvNodePool, p.NodePool),
		// values from volume spec
		fmt.Sprintf("%s=%s", EnvNamespace, req.Namespace),
		fmt.Sprintf("%s=%s", EnvVolumeName, req.Name),
		fmt.Sprintf("%s=%s", EnvVolumeID, req.ID),
		fmt.Sprintf("%s=%d", EnvCapacityMin, req.RequestedCapacityMinBytes),
		fmt.Sprintf("%s=%d", EnvCapacityMax, req.RequestedCapacityMaxBytes),
		fmt.Sprintf("%s=%s", EnvNodeID, req.NodeID),
		fmt.Sprintf("%s=%s", EnvParameters, params),
	}

	var pluginResp HostVolumePluginCreateResponse
	log := p.log.With("volume_name", req.Name, "volume_id", req.ID)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect req.Parameters and ensure it is a plain map[string]string with JSON-safe values
  2. Log the wrapped error (%w) to identify which key/value failed to marshal
  3. Rebuild the create request with simple string parameters
  4. If using a custom map type, fix or remove its MarshalJSON implementation
  5. Upgrade/verify Nomad version — this is normally an unreachable defensive branch

Example fix

// before
req := &cstructs.ClientHostVolumeCreateRequest{Parameters: badParams}
resp, err := plugin.Create(ctx, req)
// after
params := make(map[string]string, len(raw))
for k, v := range raw { params[k] = fmt.Sprintf("%v", v) }
req := &cstructs.ClientHostVolumeCreateRequest{Parameters: params}
resp, err := plugin.Create(ctx, req)
Defensive patterns

Strategy: validation

Validate before calling

params := req.Parameters
for k, v := range params {
    if k == "" { return fmt.Errorf("empty parameter key") }
    _ = v // map[string]string always marshals; otherwise inspect custom types
}
if b, err := json.Marshal(params); err != nil {
    return fmt.Errorf("parameters not serializable: %w", err)
}

Type guard

func okParams(m map[string]string) bool { return m != nil }

Try / catch

resp, err := plugin.Create(ctx, req)
if err != nil {
    if strings.Contains(err.Error(), "error marshaling volume pramaters") {
        // fix Parameters map client-side and retry once
        return fmt.Errorf("bad volume parameters: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling HostVolumePluginExternal.Create with a ClientHostVolumeCreateRequest whose Parameters map contains a value that fails json.Marshal — practically only possible if the map is not really map[string]string (e.g. custom JSON marshaler panics/returns error, or unsupported type injected elsewhere).

Common situations: A client or API layer constructing volume parameters with unexpected types; a custom type implementing MarshalJSON that returns an error; upgraded Nomad code where Parameters typing changed; memory corruption or concurrent map mutation during marshal.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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