hashicorp/nomad · error

Volume Mount (%d) references undefined volume %s

Error message

Volume Mount (%d) references undefined volume %s

What it means

Task.Validate checks every `volume_mount` against the group's declared `volume` stanzas and emits "Volume Mount (%d) references undefined volume %s" when the mounted name is not defined at group level. Volumes must be declared on the group and referenced by name from tasks.

Source

Thrown at nomad/structs/structs.go:8398

		// This task is a Connect proxy so it should not have service blocks
		if len(t.Services) > 0 {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Connect proxy task must not have a service block"))
		}
		if t.Leader {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Connect proxy task must not have leader set"))
		}

		// Ensure the proxy task has a corresponding service entry
		serviceErr := ValidateConnectProxyService(t.Kind.Value(), tg.Services)
		if serviceErr != nil {
			mErr.Errors = append(mErr.Errors, serviceErr)
		}
	}

	// Validation for volumes
	for idx, vm := range t.VolumeMounts {
		if _, ok := tg.Volumes[vm.Volume]; !ok {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Volume Mount (%d) references undefined volume %s", idx, vm.Volume))
		}

		if err := vm.Validate(); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Volume Mount (%d) is invalid: \"%w\"", idx, err))
		}
	}

	// Validate CSI Plugin Config
	if t.CSIPluginConfig != nil {
		if t.CSIPluginConfig.ID == "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig must have a non-empty PluginID"))
		}

		if !CSIPluginTypeIsValid(t.CSIPluginConfig.Type) {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig PluginType must be one of 'node', 'controller', or 'monolith', got: \"%s\"", t.CSIPluginConfig.Type))
		}

		if t.CSIPluginConfig.StagePublishBaseDir != "" && t.CSIPluginConfig.MountDir != "" &&

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Add a matching `volume` block on the group with the referenced name
  2. Fix the volume name in the task's volume_mount to match the group declaration
  3. Run `nomad job validate` to list all undefined volume references

Example fix

// before
group "app" {
  task "srv" {
    volume_mount {
      volume      = "data"
      destination = "/data"
    }
  }
}
// after
group "app" {
  volume "data" {
    type            = "host"
    source          = "data-vol"
  }
  task "srv" {
    volume_mount {
      volume      = "data"
      destination = "/data"
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

for _, vm := range task.VolumeMounts {
    if _, ok := group.Volumes[vm.Volume]; !ok {
        return fmt.Errorf("task %q mounts undefined volume %q", task.Name, vm.Volume)
    }
}

Type guard

func volumeDefined(g *structs.TaskGroup, name string) bool { _, ok := g.Volumes[name]; return ok }

Try / catch

if err := job.Validate(); err != nil {
    if strings.Contains(err.Error(), "references undefined volume") { /* declare or fix volume name */ }
}

Prevention

When it happens

Trigger: A task has `volume_mount { volume = "data" }` but the group has no `volume "data"` stanza, or the names differ (typo/case).

Common situations: Renaming a group volume without updating task mounts; moving a task between groups that lack the volume; host_volume/CSI name mismatches after migration to the volume stanza syntax.

Related errors


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