hashicorp/nomad · error

unsupported primitive type

Error message

unsupported primitive type

What it means

hclutils.ctyValueToInterface converts cty values (HCL expression results) into Go interface values. It handles cty.Number and cty.Bool primitives; any other primitive cty type (e.g. cty.String reaching this branch unexpectedly, or a new primitive kind) hits the default and panics, since the type system should prevent it.

Source

Thrown at helper/pluginutils/hclutils/util.go:125

	}

	switch {
	case t.IsPrimitiveType():
		switch t {
		case cty.String:
			return val.AsString(), nil
		case cty.Number:
			if val.RawEquals(cty.PositiveInfinity) {
				return math.Inf(1), nil
			}
			if val.RawEquals(cty.NegativeInfinity) {
				return math.Inf(-1), nil
			}
			return smallestNumber(val.AsBigFloat()), nil
		case cty.Bool:
			return val.True(), nil
		default:
			panic("unsupported primitive type")
		}

	case t.IsListType(), t.IsSetType(), t.IsTupleType():
		result := []interface{}{}

		it := val.ElementIterator()
		for it.Next() {
			_, ev := it.Element()
			evi, err := ctyValueToInterface(ev)
			if err != nil {
				return nil, err
			}
			result = append(result, evi)
		}
		return result, nil

	case t.IsMapType():
		result := map[string]interface{}{}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Add a case for the missing primitive type (e.g. cty.String -> val.AsString()) in ctyValueToInterface
  2. Verify the value's type before conversion with t == cty.String etc., and route strings through the correct branch
  3. Check the HCL job/config expression for constructs producing unexpected primitive types
  4. Report a bug to Nomad with the job spec that triggered it

Example fix

// before
default:
    panic("unsupported primitive type")
// after
case t == cty.String:
    return val.AsString(), nil
default:
    return nil, fmt.Errorf("unsupported primitive type: %s", t.FriendlyName())
Defensive patterns

Strategy: type-guard

Validate before calling

func convertiblePrimitive(t cty.Type) bool {
    return t == cty.Number || t == cty.Bool || t == cty.String
}
if !convertiblePrimitive(val.Type()) { return nil }

Type guard

func ctyToIfaceSafe(val cty.Value) (out interface{}, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("unsupported cty type %s", val.Type().FriendlyName())
        }
    }()
    return hclutils.CtyValueToMapInterface(val), nil
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        err = fmt.Errorf("cty conversion failed: %v", r)
    }
}()

Prevention

When it happens

Trigger: Evaluating an HCL expression whose cty primitive type is not Number or Bool in the conversion path — e.g. a string-typed cty value routed through CtyValueToMapInterface, or a newly added cty primitive type not handled by the switch.

Common situations: Job specs using HCL features producing primitive types the converter doesn't expect; plugin/task config schemas drifting from what ctyValueToInterface handles; custom cty types in forked code paths.

Related errors


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