hashicorp/nomad · error

invalid type for node variable: %T

Error message

invalid type for node variable: %T

What it means

After locating allMap["node"], AllValues asserts it is a map[string]any so attr/meta subtrees can be attached. If something stored a non-map value under the 'node' key (only possible via a 'node' env-var-style key colliding with a cty.Value or string), the type assertion fails and this fatal error is returned with the offending Go type.

Source

Thrown at client/taskenv/env.go:327

	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
	}

	return tree, errs, nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Ensure no top-level key exactly named "node" (without a dot segment) is added to EnvMap or NodeAttrs; use node.<field> keys
  2. Store only strings under NodeAttrs/EnvMap keys; reserve cty.Value for the final tree, not the intermediate maps
  3. Inspect the %T in the message to find which code path inserted the wrong type
  4. If inside Nomad core with no custom plugins, report upstream — this should be unreachable

Example fix

// before: scalar clobbers the node object
envMap["node"] = "wrong"
// after: nest under a dotted node key
envMap["node.custom"] = "value"
Defensive patterns

Strategy: type-guard

Validate before calling

// Go: before calling AllValues, ensure the 'node' slot is a map
if v, ok := allMap["node"]; ok {
    if _, isMap := v.(map[string]any); !isMap {
        return fmt.Errorf("node variable has non-map type %T; remove direct 'node' keys", v)
    }
}

Type guard

// Go
func nodeMap(all map[string]any) (map[string]any, bool) {
    v, ok := all["node"]
    if !ok {
        return nil, false
    }
    m, ok := v.(map[string]any)
    return m, ok
}

Try / catch

// Go
_, _, err := tenv.AllValues()
if err != nil && strings.HasPrefix(err.Error(), "invalid type for node variable") {
    return fmt.Errorf("a non-dotted 'node' key overwrote the node object: %w", err)
}

Prevention

When it happens

Trigger: An entry keyed under the 'node' path in EnvMap/NodeAttrs resolved to a non-map (e.g. a scalar overwrote the 'node' object, or a cty.Value was added via addNestedKey so allMap["node"] is not map[string]any).

Common situations: Custom code or tests inserting a key like "node" (no dot) directly into EnvMap/NodeAttrs; mixing raw cty.Value objects into the nested map before AllValues; client plugins feeding unexpected types into the env builder.

Related errors


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