{"record":{"id":"83916a9e901c9ba1","repo":"hashicorp/nomad","slug":"validating-volume-q-update-failed-v","errorCode":null,"errorMessage":"validating volume %q update failed: %v","messagePattern":"validating volume %q update failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/host_volume_endpoint.go","lineNumber":442,"sourceCode":"\t\treturn nil, err // should never hit, bail out\n\t}\n\tif ns == nil {\n\t\treturn nil, fmt.Errorf(\"volume validation failed: no such namespace %q\", vol.Namespace)\n\t}\n\n\t// validate any update we're making\n\tvar existing *structs.HostVolume\n\tif vol.ID != \"\" {\n\t\texisting, err = snap.HostVolumeByID(nil, vol.Namespace, vol.ID, true)\n\t\tif err != nil {\n\t\t\treturn nil, err // should never hit, bail out\n\t\t}\n\t\tif existing == nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot update volume %q: volume does not exist\", vol.ID)\n\t\t}\n\t\terr = vol.ValidateUpdate(existing)\n\t\tif err != nil {\n\t\t\treturn existing, fmt.Errorf(\"validating volume %q update failed: %v\", vol.ID, err)\n\t\t}\n\t}\n\treturn existing, nil\n}\n\n// validateVolumeForState ensures that any references to node IDs or node pools are valid\nfunc (v *HostVolume) validateVolumeForState(vol *structs.HostVolume, snap *state.StateSnapshot) error {\n\tvar poolFromExistingNode string\n\tif vol.NodeID != \"\" {\n\t\tnode, err := snap.NodeByID(nil, vol.NodeID)\n\t\tif err != nil {\n\t\t\treturn err // should never hit, bail out\n\t\t}\n\t\tif node == nil {\n\t\t\treturn fmt.Errorf(\"node %q does not exist\", vol.NodeID)\n\t\t}\n\t\tpoolFromExistingNode = node.NodePool\n\t}","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/host_volume_endpoint.go#L424-L460","documentation":"After an existing volume is found for an update, Nomad runs vol.ValidateUpdate(existing) to enforce which fields may change (e.g. disallowed mutations of an in-use volume). A policy violation in the update is reported with this wrapped message naming the volume ID. The wrapped error explains which field change is not permitted.","triggerScenarios":"Calling Create or Register with a volume ID that exists, but attempting to mutate immutable or constrained fields (e.g. changing node ID, host path, or other fields ValidateUpdate forbids given the existing volume's state).","commonSituations":"Trying to move a volume to another node by editing the spec; changing host_path on an existing volume; drift-checking tools rewriting specs wholesale and touching protected fields.","solutions":["Read the inner %v error to see which field change was rejected.","Revert the disallowed field to its existing value in the spec.","Delete and re-create the volume if the field genuinely must change (data-migration permitting).","Restrict automation to updating only mutable fields."],"exampleFix":"// before\nvolume {\n  id        = \"3f2a...\"\n  host_path = \"/data/new\"  // immutable on existing volume\n}\n// after\nvolume {\n  id        = \"3f2a...\"\n  host_path = \"/data\"  // keep existing value\n}","handlingStrategy":"validation","validationCode":"existing, _, _ := client.HostVolumes().Get(vol.Namespace, vol.ID, nil)\nif existing != nil && existing.HostPath != vol.HostPath {\n    return errors.New(\"host_path is immutable; recreate the volume instead\")\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"update failed\") {\n    // revert the disallowed field change indicated by the wrapped error\n}","preventionTips":["Change only mutable fields on updates","Diff the new spec against the existing volume first","Prefer delete+recreate for structural changes","Keep spec drift tools from rewriting immutable fields"],"tags":["nomad","host-volumes","update-validation","immutable-field"],"backgroundTag":"invalid-field-update","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}