hashicorp/nomad · error

ExternalID is required

Error message

ExternalID is required

What it means

err("ExternalID is required") is produced by ClientCSINodeExpandVolumeRequest.Validate when the ExternalID field (the storage-provider-side volume ID on the external CSI storage system) is empty. It is another programmer-error guard, joined with other validation errors via errors.Join.

Source

Thrown at client/structs/csi.go:487

	Capacity *csi.CapacityRange

	// Claim currently held for the allocation (required)
	// used to determine capabilities and the mount point on the client
	Claim *structs.CSIVolumeClaim
}

func (req *ClientCSINodeExpandVolumeRequest) Validate() error {
	var err error
	// These should not occur during normal operations; they're here
	// mainly to catch potential programmer error.
	if req.PluginID == "" {
		err = errors.Join(err, errors.New("PluginID is required"))
	}
	if req.VolumeID == "" {
		err = errors.Join(err, errors.New("VolumeID is required"))
	}
	if req.ExternalID == "" {
		err = errors.Join(err, errors.New("ExternalID is required"))
	}
	if req.Claim == nil {
		err = errors.Join(err, errors.New("Claim is required"))
	} else if req.Claim.AllocationID == "" {
		err = errors.Join(err, errors.New("Claim.AllocationID is required"))
	}
	return err
}

type ClientCSINodeExpandVolumeResponse struct {
	CapacityBytes int64
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Populate ExternalID from the volume's remote/external ID (volume.RemoteID()) before the RPC
  2. Verify the volume was fully created/published on the external storage system
  3. Add a pre-call check that req.ExternalID != ""
  4. Inspect the joined Validate error to catch all missing fields at once

Example fix

// before
req := &cstructs.ClientCSINodeExpandVolumeRequest{PluginID: pluginID, VolumeID: vol.ID}
// after
req := &cstructs.ClientCSINodeExpandVolumeRequest{PluginID: pluginID, VolumeID: vol.ID, ExternalID: vol.RemoteID()}
Defensive patterns

Strategy: validation

Validate before calling

if err := req.Validate(); err != nil { return err }
if req.ExternalID == "" { return errors.New("ExternalID (remote volume ID) must be set") }

Try / catch

if err := req.Validate(); err != nil {
    if strings.Contains(err.Error(), "ExternalID is required") {
        // query the controller for the remote volume ID, then retry
        return resolveExternalIDAndRetry()
    }
    return err
}

Prevention

When it happens

Trigger: Submitting a ClientCSINodeExpandVolumeRequest with ExternalID == "" — the remote/external volume ID was never populated from the controller's response or was lost during request construction.

Common situations: Volume created without successful ControllerPublishVolume/external ID sync, partially published volumes, or bugs copying the Nomad volume struct into the client request.

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/77536766cb0cf5a8. Report an issue: GitHub.