hashicorp/nomad · error

cannot specify Accessor ID

Error message

cannot specify Accessor ID

What it means

lookupExternalNodeID could not find a node in the Nomad state store matching claim.NodeID and returns ErrUnknownNode (wrapped via %w so errors.Is works). Callers (controllerPublishVolume/controllerUnpublishVolume) treat this specially — unpublish skips detach and marks the claim ReadyToFree.

Source

Thrown at api/acl.go:133

	}
	return &resp, wm, nil
}

// List is used to dump all of the tokens.
func (a *ACLTokens) List(q *QueryOptions) ([]*ACLTokenListStub, *QueryMeta, error) {
	var resp []*ACLTokenListStub
	qm, err := a.client.query("/v1/acl/tokens", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return resp, qm, nil
}

// Create is used to create a token with server-generated AccessorID and
// SecretID. Use Upload to create a token with pre-specified IDs.
func (a *ACLTokens) Create(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
	if token.AccessorID != "" {
		return nil, nil, errors.New("cannot specify Accessor ID")
	}
	var resp ACLToken
	wm, err := a.client.put("/v1/acl/token", token, &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return &resp, wm, nil
}

// Upload is used to create a client token with pre-specified AccessorID and
// SecretID. Management tokens cannot be uploaded and must be created with Create.
func (a *ACLTokens) Upload(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
	if token.AccessorID == "" {
		return nil, nil, errors.New("missing accessor ID")
	}
	if token.SecretID == "" {
		return nil, nil, errors.New("missing secret ID")
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check nomad node status to see if the node re-registered under a new ID
  2. Update the claim/volume to reference the current node ID, or re-run the workload so a fresh claim is created
  3. For unpublish, no action needed — Nomad marks claim ReadyToFree and frees it
  4. Match with errors.Is(err, structs.ErrUnknownNode) in custom tooling rather than string compare

Example fix

// before
if err.Error() == "node not found abc123" { retry() }
// after
if errors.Is(err, structs.ErrUnknownNode) {
    // node permanently gone: release claim instead of retrying
    claim.State = structs.CSIVolumeClaimStateReadyToFree
}
Defensive patterns

Strategy: try-catch

Validate before calling

node, _, err := client.Nodes().Info(nodeID, nil)
if err != nil || node == nil { /* treat as unknown node: skip detach, free claim */ }

Try / catch

if errors.Is(err, structs.ErrUnknownNode) {
    // node permanently gone — don't retry, mark claim ReadyToFree
    claim.State = structs.CSIVolumeClaimStateReadyToFree
}

Prevention

When it happens

Trigger: Publish/unpublish of a volume claim whose NodeID references a deregistered, GC'd, or purged Nomad client; stale claims surviving node removal.

Common situations: Node was drained and garbage collected with an active claim; cluster state restored from backup without the node; client ID changed after re-provisioning (autoscaled nodes).

Related errors


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