hashicorp/nomad · error

missing NodeID

Error message

missing NodeID

What it means

ControllerPublishVolumeRequest.Validate() rejects requests with an empty NodeID, the node identity the plugin needs to attach the volume to. The provider's attach API requires a target node; an empty NodeID is ambiguous and rejected.

Source

Thrown at plugins/csi/plugin.go:417

		return nil
	}

	return &csipbv1.ControllerPublishVolumeRequest{
		VolumeId:         r.ExternalID,
		NodeId:           r.NodeID,
		Readonly:         r.ReadOnly,
		VolumeCapability: r.VolumeCapability.ToCSIRepresentation(),
		Secrets:          r.Secrets,
		VolumeContext:    r.VolumeContext,
	}
}

func (r *ControllerPublishVolumeRequest) Validate() error {
	if r.ExternalID == "" {
		return errors.New("missing volume ID")
	}
	if r.NodeID == "" {
		return errors.New("missing NodeID")
	}
	return nil
}

type ControllerPublishVolumeResponse struct {
	PublishContext map[string]string
}

type ControllerUnpublishVolumeRequest struct {
	ExternalID string
	NodeID     string
	Secrets    structs.CSISecrets
}

func (r *ControllerUnpublishVolumeRequest) ToCSIRepresentation() *csipbv1.ControllerUnpublishVolumeRequest {
	if r == nil {
		return nil
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set NodeID to the provider node ID returned by NodeGetInfo (or the plugin's registered node identifier)
  2. Ensure the node has completed registration/fingerprinting with the plugin before publishing volumes to it
  3. Check that the caller isn't confusing the CSI node name with the provider instance ID

Example fix

// before
req := &csi.ControllerPublishVolumeRequest{
    ExternalID: volumeExternalID,
    NodeID:     "",
}
// after
nodeInfo, err := nodeClient.NodeGetInfo(ctx, &csi.NodeGetInfoRequest{})
// after
req := &csi.ControllerPublishVolumeRequest{
    ExternalID: volumeExternalID,
    NodeID:     nodeInfo.NodeID,
}
Defensive patterns

Strategy: validation

Validate before calling

func validateNodeID(req *csi.ControllerPublishVolumeRequest) error {
    if req.NodeID == "" {
        return errors.New("NodeID must be the provider node ID from NodeGetInfo")
    }
    return nil
}

Type guard

func hasNodeID(req *csi.ControllerPublishVolumeRequest) bool {
    return req != nil && req.NodeID != ""
}

Try / catch

if err := req.Validate(); err != nil {
    if strings.Contains(err.Error(), "missing NodeID") {
        return fmt.Errorf("controller publish refused: fetch NodeID via NodeGetInfo after node registration: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ControllerPublishVolume with NodeID empty, e.g. the node was never registered with the provider or the caller passed a zero-value request.

Common situations: Node fingerprinting/registration not completed so the provider node ID was never recorded; using the node's hostname instead of the provider-assigned node ID; race where publish starts before NodeRegister finishes.

Related errors


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