go-task/task · error

enum reference %q must contain only strings

Error message

enum reference %q must contain only strings

What it means

resolveEnumRefs in variables.go validates every element of a resolved enum list and requires all items to be strings. If any element is a number, boolean, map, or other non-string type, the library throws this error because prompt enum choices are rendered and compared as strings.

Source

Thrown at variables.go:525

		return nil
	}
	for _, v := range requires.Vars {
		if v.Enum == nil || v.Enum.Ref == "" {
			continue
		}
		resolved := templater.ResolveRef(v.Enum.Ref, cache)
		if cache.Err() != nil {
			return cache.Err()
		}
		arr, ok := resolvedAsAnySlice(resolved)
		if !ok {
			return fmt.Errorf("enum reference %q must resolve to a list", v.Enum.Ref)
		}
		strValues := make([]string, 0, len(arr))
		for _, item := range arr {
			s, ok := item.(string)
			if !ok {
				return fmt.Errorf("enum reference %q must contain only strings", v.Enum.Ref)
			}
			strValues = append(strValues, s)
		}
		v.Enum.Value = strValues
	}
	return nil
}

// product generates the cartesian product of the input map of slices.
func product(matrix *ast.Matrix) []map[string]any {
	if matrix.Len() == 0 {
		return nil
	}

	// Start with an empty product result
	result := []map[string]any{{}}

	// Iterate over each slice in the slices

View on GitHub (pinned to 385e5ad92a)

Solutions

  1. Quote every element in the YAML list so it parses as a string (e.g. ['1', '2']).
  2. If dynamic, make the command emit an array of JSON strings.
  3. Convert numeric items at the source, e.g. JSON: ["8080", "9090"].
  4. Keep enum lists string-only by convention in the taskfile.

Example fix

// before
vars:
  PORTS: [8080, 9090]
prompt:
  enum:
    ref: .PORTS
// after
vars:
  PORTS: ['8080', '9090']
prompt:
  enum:
    ref: .PORTS
Defensive patterns

Strategy: type-guard

Validate before calling

func allStrings(v any) bool {
    arr, ok := v.([]any)
    if !ok { return false }
    for _, item := range arr {
        if _, ok := item.(string); !ok { return false }
    }
    return true
}
// pre-check: allStrings(mustResolve(envVarRef))

Type guard

func asStringList(v any) ([]string, bool) {
    arr, ok := v.([]any)
    if !ok { return nil, false }
    out := make([]string, 0, len(arr))
    for _, item := range arr {
        s, ok := item.(string)
        if !ok { return nil, false }
        out = append(out, s)
    }
    return out, true
}

Try / catch

task, err := compiledTask(...)
if err != nil {
    if strings.Contains(err.Error(), "must contain only strings") {
        return fmt.Errorf("quote enum values as strings in the taskfile: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: An enum ref resolves to a list containing non-string items, e.g. ENV: [1, 2, 3] or [true, false], used by a prompt variable's enum during compiledTask or resolveEnumRefForPrompt.

Common situations: Port numbers or versions written as YAML integers, booleans in a feature-flag enum, dynamic variables returning JSON arrays of numbers.

Related errors


AI-assisted analysis of go-task/task@385e5ad92a (2026-09-05). Data as JSON: /api/errors/8a023d8a7ca8a79d. Report an issue: GitHub.