temporalio/temporal · error · converter.ErrUnableToDecode

%w: list of values not allowed for type %T

Error message

%w: list of values not allowed for type %T

What it means

decodeValueTyped returns converter.ErrUnableToDecode wrapped with "list of values not allowed" when a payload decodes to a multi-element list but allowList is false and the list has more than one element. Single-element lists are unwrapped to the scalar; longer lists are rejected because the declared type is scalar. KeywordList decoding always passes allowList=false but uses its own path (DecodeKeywordList).

Source

Thrown at common/searchattribute/sadefs/encode_value.go:130

		if val == nil {
			return nil, nil
		}
		return *val, nil
	}
	var listVal []T
	if err := payload.Decode(value, &listVal); err != nil {
		return nil, err
	}
	if len(listVal) == 0 {
		return nil, nil
	}
	if allowList {
		return listVal, nil
	}
	if len(listVal) == 1 {
		return listVal[0], nil
	}
	return nil, fmt.Errorf(
		"%w: list of values not allowed for type %T",
		converter.ErrUnableToDecode,
		listVal[0],
	)
}

func DecodeKeywordList(value *commonpb.Payload) ([]string, error) {
	// Decode to []any because json.Unmarshal decodes null values to zero value,
	// i.e., if we decoded to []string, null values would become empty string,
	// which is invalid.
	dv, err := decodeValueTyped[[]any](value, false)
	if err != nil {
		return nil, err
	}
	if dv == nil {
		return nil, nil
	}
	// Validate that every value is a string.

View on GitHub (pinned to bde624efd1)

Solutions

  1. Pass allowList=true to DecodeValue if the underlying field is genuinely multi-valued.
  2. Align the declared INDEXED_VALUE_TYPE with how the value was encoded (list vs scalar).
  3. Pre-check with DecodeKeywordList or the converter when the field may contain multiple values.

Example fix

// before
val, err := sadefs.DecodeValue(payload, enumspb.INDEXED_VALUE_TYPE_KEYWORD, false)
// after
val, err := sadefs.DecodeValue(payload, enumspb.INDEXED_VALUE_TYPE_KEYWORD, true) // multi-valued field
Defensive patterns

Strategy: validation

Validate before calling

if len(values) > 1 && !allowList {
    return fmt.Errorf("field is multi-valued; pass allowList=true")
}

Try / catch

if errors.Is(err, converter.ErrUnableToDecode) { /* retry with allowList=true */ }

Prevention

When it happens

Trigger: DecodeValue with a scalar type (e.g. Keyword or Bool) whose payload converter yields a []any with 2+ elements — i.e. the value was written as a list but is being read as a scalar.

Common situations: Type of a search attribute changed from a list-ish/multi-value to scalar (or vice versa) between write and read; Elasticsearch multi-valued fields decoded without allowList=true.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/040e11f336e016ee. Report an issue: GitHub.