hashicorp/nomad · error

validation: %s

Error message

validation: %s

What it means

This aggregates all field-validation failures found while validating a CSIVolume struct into a single error prefixed with 'validation: '. It is thrown when user-defined volume fields violate constraints — here, topology requests whose Segments field is empty — or any of the other checks in the same function (empty RequestedCapabilities, invalid AccessMode/Capability pairs, bad MountFlags, etc.).

Source

Thrown at nomad/structs/csi.go:771

		errs = append(errs, "only one of snapshot_id and clone_id is allowed")
	}
	if len(v.RequestedCapabilities) == 0 {
		errs = append(errs, "must include at least one capability block")
	}
	if v.RequestedTopologies != nil {
		for _, t := range v.RequestedTopologies.Required {
			if t != nil && len(t.Segments) == 0 {
				errs = append(errs, "required topology is missing segments field")
			}
		}
		for _, t := range v.RequestedTopologies.Preferred {
			if t != nil && len(t.Segments) == 0 {
				errs = append(errs, "preferred topology is missing segments field")
			}
		}
	}
	if len(errs) > 0 {
		return fmt.Errorf("validation: %s", strings.Join(errs, ", "))
	}
	return nil
}

// Merge updates the mutable fields of a volume with those from
// another volume. CSIVolume has many user-defined fields which are
// immutable once set, and many fields that are not
// user-settable. Merge will return an error if we try to mutate the
// user-defined immutable fields after they're set, but silently
// ignore fields that are controlled by Nomad.
func (v *CSIVolume) Merge(other *CSIVolume) error {
	if other == nil {
		return nil
	}

	var errs *multierror.Error

	if v.Name != other.Name && other.Name != "" {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the joined message after 'validation: ' — it lists every offending field; fix each listed field in the volume spec.
  2. Provide non-empty segments in every requested/preferred topology, e.g. topology_request { segments { rack = "r1" } }.
  3. Ensure each requested_capability sets BOTH access_mode and attachment_mode and that they are compatible with the volume's declared access mode.
  4. Validate the spec locally before registering (nomad volume validate or a dry run) to catch all errs at once.

Example fix

// before
topology_request {
  segments {} # empty -> "preferred topology is missing segments field"
}
// after
topology_request {
  segments {
    rack = "rack-1"
    zone = "us-east-1a"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

func validateVolumeSpec(vol *api.CSIVolume) error {
    var errs []string
    for _, t := range append(vol.RequestedTopologies, vol.PreferredTopology) {
        if t != nil && len(t.Segments) == 0 {
            errs = append(errs, "topology missing segments")
        }
    }
    for _, c := range vol.RequestedCapabilities {
        if c.AccessMode == "" || c.AttachmentMode == "" {
            errs = append(errs, "capability needs both access_mode and attachment_mode")
        }
    }
    if len(errs) > 0 {
        return fmt.Errorf("validation: %s", strings.Join(errs, ", "))
    }
    return nil
}
// run before nomad volume register

Type guard

func topologyHasSegments(t *structs.CSITopology) bool {
    return t == nil || len(t.Segments) > 0
}

Try / catch

err := vol.Validate()
if err != nil {
    var verr *fmt.wrapError
    if strings.HasPrefix(err.Error(), "validation: ") {
        for _, problem := range strings.Split(strings.TrimPrefix(err.Error(), "validation: "), ", ") {
            log.Printf("volume spec problem: %s", problem)
        }
        return err // fix the spec; retrying will not help
    }
    return err
}

Prevention

When it happens

Trigger: Calling CSIVolume.Validate (via nomad volume register / job volume validation RPC) when: requested topologies or preferred topologies have empty Segments; a capability has AccessMode but no AttachmentMode (or vice versa); requested capabilities conflict with the volume's declared AccessMode; mount flags set on non-filesystem volumes.

Common situations: Registering a volume with 'topology_request: {segments: {}}' in an HCL/JSON volume spec; copy-pasting a volume spec with capability blocks missing attachment_mode; operator tightening validation in a newer Nomad version so previously-registered specs now fail.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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