temporalio/temporal · error

panic(err)

Error message

panic(err)

What it means

MustEncodeValue encodes a search attribute value into a Payload and is the 'must' variant: it panics instead of returning an error. Any encoding failure (unsupported value type, value not matching the declared IndexedValueType) is raised as a panic.

Source

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

// EncodeValue encodes search attribute value and IndexedValueType to Payload.
func EncodeValue(val any, t enumspb.IndexedValueType) (*commonpb.Payload, error) {
	valPayload, err := payload.Encode(val)
	if err != nil {
		return nil, err
	}

	SetMetadataType(valPayload, t)
	return valPayload, nil
}

// MustEncodeValue encodes search attribute value and IndexedValueType to Payload.
// Panics if it fails to encode.
func MustEncodeValue(val any, t enumspb.IndexedValueType) *commonpb.Payload {
	valPayload, err := EncodeValue(val, t)
	if err != nil {
		// nolint:forbidigo
		panic(err)
	}
	return valPayload
}

// DecodeValue decodes search attribute value from Payload using (in order):
// 1. passed type t.
// 2. type from MetadataType field, if t is not specified.
// allowList allows list of values when it's not keyword list type.
func DecodeValue(
	value *commonpb.Payload,
	t enumspb.IndexedValueType,
	allowList bool,
) (any, error) {
	if t == enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED {
		t = GetMetadataType(value)
	}
	if t == enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED {
		return nil, fmt.Errorf("%w: %v", ErrInvalidType, t)

View on GitHub (pinned to bde624efd1)

Solutions

  1. Pre-validate the value type matches the IndexedValueType before calling (or use non-panicking EncodeValue and handle err)
  2. Use EncodeValue instead of MustEncodeValue where the value's type is not statically known
  3. Fix the search attribute type mapping so the declared type matches the actual value

Example fix

// before
payload := sadefs.MustEncodeValue(val, enumspb.INDEXED_VALUE_TYPE_INT) // panics if val is string
// after
payload, err := sadefs.EncodeValue(val, enumspb.INDEXED_VALUE_TYPE_INT)
if err != nil {
    return fmt.Errorf("encode search attribute: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

switch val.(type) {
case string, int, bool, float64, time.Time, []string:
    // plausibly encodable
default:
    return fmt.Errorf("unsupported search attribute value %T", val)
}
payload, err := sadefs.EncodeValue(val, saType)
if err != nil { return err }

Try / catch

func() (p *commonpb.Payload) {
    defer func() {
        if recover() != nil { p = nil }
    }()
    return sadefs.MustEncodeValue(val, saType)
}()

Prevention

When it happens

Trigger: Calling MustEncodeValue with a Go value whose type does not match the given enumspb.IndexedValueType (e.g. MustEncodeValue("abc", enumspb.INDEXED_VALUE_TYPE_INT)), or with a nil/unsupported type the encoder cannot serialize.

Common situations: Populating search attributes from untyped user data; schema/type changes between versions where an attribute's declared type changed; reflecting on struct fields whose runtime type differs from the declared attribute type.

Related errors


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