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
- Pass allowList=true to DecodeValue if the underlying field is genuinely multi-valued.
- Align the declared INDEXED_VALUE_TYPE with how the value was encoded (list vs scalar).
- 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
- Match allowList to the field's actual cardinality in the visibility store
- Keep the attribute's declared type stable across write and read paths
- Prefer DecodeKeywordList for known multi-valued keyword fields
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.