hashicorp/nomad · error

no node events given for node %q

Error message

no node events given for node %q

What it means

EmitEvents validates that every node ID key in args.NodeEvents maps to a non-empty event slice. If any individual node has zero events, the whole RPC is rejected with this per-node error. This catches partially-empty batches that pass the overall non-empty check.

Source

Thrown at nomad/node_endpoint.go:1991

	}
	n.srv.MeasureRPCRate("node", structs.RateMetricWrite, args)
	if err != nil {
		return structs.ErrPermissionDenied
	}
	defer metrics.MeasureSince([]string{"nomad", "client", "emit_events"}, time.Now())

	if len(args.NodeEvents) == 0 {
		return fmt.Errorf("no node events given")
	}

	callerNodeID := auth.AuthenticatedNodeID(args.GetIdentity())
	if callerNodeID == "" {
		return structs.ErrPermissionDenied
	}

	for nodeID, events := range args.NodeEvents {
		if len(events) == 0 {
			return fmt.Errorf("no node events given for node %q", nodeID)
		}

		node, err := n.srv.State().NodeByID(nil, nodeID)
		if err != nil {
			return err
		}
		if node == nil || !aclObj.AllowClientOp(node.NodePool) {
			return structs.ErrPermissionDenied
		}
		if nodeID != callerNodeID {
			return structs.ErrPermissionDenied
		}
	}

	_, index, err := n.srv.raftApply(structs.UpsertNodeEventsType, args)
	if err != nil {
		n.logger.Error("upserting node events failed", "error", err)
		return err

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Only add a node's entry to the NodeEvents map when at least one event exists
  2. Sanitize the map before the RPC: delete keys with empty slices
  3. Review the emitting code for race conditions that empty a slice after key creation

Example fix

// before
nodeEvents[nodeID] = pendingEvents[nodeID] // may be empty
// after
if len(pendingEvents[nodeID]) > 0 {
    nodeEvents[nodeID] = pendingEvents[nodeID]
}
Defensive patterns

Strategy: validation

Validate before calling

for id, evs := range args.NodeEvents {
    if len(evs) == 0 {
        delete(args.NodeEvents, id)
    }
}
if len(args.NodeEvents) == 0 { return nil }

Type guard

func allEntriesNonEmpty(m map[string][]*structs.NodeEvent) bool {
    for _, v := range m {
        if len(v) == 0 { return false }
    }
    return len(m) > 0
}

Try / catch

err := client.Nodes().EmitEvents(args)
if err != nil && strings.Contains(err.Error(), "no node events given for node") {
    // sanitize the map and rebuild the batch
}

Prevention

When it happens

Trigger: A Node.EmitEvents request whose NodeEvents map contains a key with an empty []*NodeEvent value, e.g. map[nodeID:abc]{}, from a client-side event buffer that created an entry without appending events.

Common situations: Custom client tooling or patched agents building the events map incrementally — inserting a placeholder key before events are appended; concurrency bugs where events are drained from a slice after the key is created.

Related errors


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