hashicorp/terraform · error

input list must not contain null string

Error message

input list must not contain null string

What it means

Thrown by `transpose()` (TransposeFunc) while iterating the inner list of a map value, when an element of that inner list is null. transpose() builds reversed string-keyed lists, so a null element (which would become a key) is rejected. The input map type is map(list(string)), but a null can still appear at runtime.

Solutions

  1. Compact each inner list to drop nulls: `{ for k, v in var.m : k => compact(v) }`.
  2. Filter at the source so inner lists never contain null.
  3. Use `[for s in v : s if s != null]` per inner list.

Example fix

// before
locals { t = transpose(var.tags) }   # inner lists contain nulls

// after
locals { t = transpose({ for k, v in var.tags : k => compact(v) }) }
Defensive patterns

Strategy: validation

Validate before calling

# HCL: compact inner lists to remove nulls
locals { t = transpose({ for k, v in var.m : k => compact(v) }) }

Type guard

# HCL: filter nulls explicitly
locals { t = transpose({ for k, v in var.m : k => [for x in v : x if x != null] }) }

Prevention

When it happens

Trigger: Calling transpose with a map whose list contains a null, e.g. `transpose({a = ["x", null]})`. Data sourced from a nullable nested attribute.

Common situations: A nested variable or datasource attribute producing nulls inside the inner lists. Optional inner elements resolving to null.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/8f01654081f86d0a. Report an issue: GitHub.

Appendix: source

Thrown at internal/lang/funcs/collection.go:591

	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		inputMap := args[0]
		if !inputMap.IsWhollyKnown() {
			return cty.UnknownVal(retType), nil
		}

		outputMap := make(map[string]cty.Value)
		tmpMap := make(map[string][]string)

		for it := inputMap.ElementIterator(); it.Next(); {
			inKey, inVal := it.Element()
			if inVal.IsNull() {
				return cty.MapValEmpty(cty.List(cty.String)), errors.New("input must not contain null list")
			}
			for iter := inVal.ElementIterator(); iter.Next(); {
				_, val := iter.Element()
				if val.IsNull() {
					return cty.MapValEmpty(cty.List(cty.String)), errors.New("input list must not contain null string")
				}
				if !val.Type().Equals(cty.String) {
					return cty.MapValEmpty(cty.List(cty.String)), errors.New("input must be a map of lists of strings")
				}

				outKey := val.AsString()
				if _, ok := tmpMap[outKey]; !ok {
					tmpMap[outKey] = make([]string, 0)
				}
				outVal := tmpMap[outKey]
				outVal = append(outVal, inKey.AsString())
				sort.Strings(outVal)
				tmpMap[outKey] = outVal
			}
		}

		for outKey, outVal := range tmpMap {
			values := make([]cty.Value, 0)

View on GitHub (pinned to d32a084675)