hashicorp/nomad · error

missing node variable

Error message

missing node variable

What it means

TaskEnv.AllValues builds the HCL2 variable tree (env, node, attr, meta) used for interpolation. It requires a 'node' object in the assembled map; since node values normally come from t.NodeAttrs (e.g. 'node.name', 'node.datacenter'), their absence means the TaskEnv was never populated with node data, which the function treats as a fatal programming/setup error.

Source

Thrown at client/taskenv/env.go:323

		}
	}

	// Prepare task-based secrets for use in interpolation
	for k, v := range t.TaskSecrets {
		if err := addNestedKey(allMap, k, v); err != nil {
			errs[k] = err
		}
	}

	// Add flat envMap as a Map to allMap so users can access any key via
	// HCL2's indexing syntax: ${env["foo...bar"]}
	allMap["env"] = cty.MapVal(envMap)

	// Add meta and attr to node if they exist to properly namespace things
	// a bit.
	nodeMapI, ok := allMap["node"]
	if !ok {
		return nil, nil, fmt.Errorf("missing node variable")
	}
	nodeMap, ok := nodeMapI.(map[string]any)
	if !ok {
		return nil, nil, fmt.Errorf("invalid type for node variable: %T", nodeMapI)
	}
	if attrMap, ok := allMap["attr"]; ok {
		nodeMap["attr"] = attrMap
	}
	if metaMap, ok := allMap["meta"]; ok {
		nodeMap["meta"] = metaMap
	}

	// ctyify the entire tree of strings and maps
	tree, err := ctyify(allMap)
	if err != nil {
		// This should not be possible and is likely a programming
		// error. Invalid user input should be cleaned earlier.
		return nil, nil, err

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Build the TaskEnv via the standard client path (alloc runner's envBuilder with Node attributes) before calling AllValues
  2. In tests/utilities, populate NodeAttrs with at least node.name/node.datacenter equivalents so a 'node' object exists
  3. Guard the call: only invoke AllValues on TaskEnv instances that have non-empty NodeAttrs
  4. If hit in a Nomad hook, capture the alloc/hook context and file an upstream bug — docs call this 'likely a programming error'

Example fix

// before: AllValues on a bare TaskEnv panics into error
tenv := &taskenv.TaskEnv{}
vars, _, err := tenv.AllValues()
// after: build with node attrs first
tenv := taskenv.NewEmptyBuilder().UpdateNode(node).Build()
vars, _, err := tenv.AllValues()
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify the TaskEnv has node attributes before calling AllValues
func hasNodeAttrs(t *taskenv.TaskEnv) bool {
    if t == nil {
        return false
    }
    for k := range t.NodeAttrs {
        if strings.HasPrefix(k, "node.") {
            return true
        }
    }
    return false
}

Type guard

// Go
func builtTaskEnv(t *taskenv.TaskEnv) (*taskenv.TaskEnv, bool) {
    if t == nil || len(t.NodeAttrs) == 0 {
        return nil, false
    }
    return t, true
}

Try / catch

// Go
vars, errs, err := tenv.AllValues()
if err != nil {
    if strings.Contains(err.Error(), "missing node variable") {
        return nil, fmt.Errorf("TaskEnv not built with node attributes; use the client env builder: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: AllValues() is called on a TaskEnv whose NodeAttrs map contains no keys that nest under 'node' (no node.* attributes were added via Build(), or the empty/partial TaskEnv was constructed without node information).

Common situations: Calling AllValues on a zero-value or manually constructed TaskEnv instead of one built by the client; tests instantiating TaskEnv with only EnvMap; hooks running before node attributes are attached (e.g. pre-restore paths).

Related errors


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