temporalio/temporal · error

unknown task predicate type: %T

Error message

unknown task predicate type: %T

What it means

ToPersistencePredicate converts a tasks.Predicate to its persistence protobuf form via a type switch. The default branch panics when handed a predicate implementation it does not recognize, meaning a new task predicate type was added without extending this converter.

Source

Thrown at service/history/queues/convert.go:128

		return ToPersistenceEmptyPredicate(predicate)
	case *predicates.AndImpl[tasks.Task]:
		return ToPersistenceAndPredicate(predicate)
	case *predicates.OrImpl[tasks.Task]:
		return ToPersistenceOrPredicate(predicate)
	case *predicates.NotImpl[tasks.Task]:
		return ToPersistenceNotPredicate(predicate)
	case *tasks.NamespacePredicate:
		return ToPersistenceNamespaceIDPredicate(predicate)
	case *tasks.TypePredicate:
		return ToPersistenceTaskTypePredicate(predicate)
	case *tasks.DestinationPredicate:
		return ToPersistenceDestinationPredicate(predicate)
	case *tasks.OutboundTaskGroupPredicate:
		return ToPersistenceOutboundTaskGroupPredicate(predicate)
	case *tasks.OutboundTaskPredicate:
		return ToPersistenceOutboundTaskPredicate(predicate)
	default:
		panic(fmt.Sprintf("unknown task predicate type: %T", predicate))
	}
}

func FromPersistencePredicate(
	predicate *persistencespb.Predicate,
) tasks.Predicate {
	switch predicate.GetPredicateType() {
	case enumsspb.PREDICATE_TYPE_UNIVERSAL:
		return FromPersistenceUniversalPredicate(predicate.GetUniversalPredicateAttributes())
	case enumsspb.PREDICATE_TYPE_EMPTY:
		return FromPersistenceEmptyPredicate(predicate.GetEmptyPredicateAttributes())
	case enumsspb.PREDICATE_TYPE_AND:
		return FromPersistenceAndPredicate(predicate.GetAndPredicateAttributes())
	case enumsspb.PREDICATE_TYPE_OR:
		return FromPersistenceOrPredicate(predicate.GetOrPredicateAttributes())
	case enumsspb.PREDICATE_TYPE_NOT:
		return FromPersistenceNotPredicate(predicate.GetNotPredicateAttributes())
	case enumsspb.PREDICATE_TYPE_NAMESPACE_ID:

View on GitHub (pinned to bde624efd1)

Solutions

  1. Add a case for the concrete predicate type in the type switch, delegating to a new ToPersistence... converter
  2. Register the new PREDICATE_TYPE in enumsspb and regenerate proto code (make proto / make update-go-api)
  3. Add a unit test in convert_test.go covering the new predicate round-trip
  4. If using a vendored/older temporal, upgrade so the predicate type is supported

Example fix

// before
default:
    panic(fmt.Sprintf("unknown task predicate type: %T", predicate))
// after
case *tasks.MyNewPredicate:
    return ToPersistenceMyNewPredicate(predicate)
default:
    panic(fmt.Sprintf("unknown task predicate type: %T", predicate))
Defensive patterns

Strategy: type-guard

Validate before calling

switch p.(type) {
case *tasks.AllPredicate, *tasks.AndPredicate, *tasks.OrPredicate, *tasks.NotPredicate, *tasks.DestinationPredicate, *tasks.OutboundTaskGroupPredicate, *tasks.OutboundTaskPredicate:
    // safe to convert
}

Type guard

func isConvertiblePredicate(p tasks.Predicate) bool {
    switch p.(type) {
    case *tasks.AllPredicate, *tasks.AndPredicate, *tasks.OrPredicate,
        *tasks.NotPredicate, *tasks.DestinationPredicate,
        *tasks.OutboundTaskGroupPredicate, *tasks.OutboundTaskPredicate:
        return true
    default:
        return false
    }
}

Try / catch

func safeToConvert(p tasks.Predicate) (out *persistencespb.Predicate) {
    defer func() {
        if r := recover(); r != nil {
            out = nil
        }
    }()
    out = queues.ToPersistencePredicate(p)
    return
}

Prevention

When it happens

Trigger: Calling ToPersistencePredicate (directly or via ToPersistenceScope/And/Or/Not combinators) with a custom or newly added tasks.Predicate implementation not covered by the switch cases.

Common situations: Developers adding a new predicate type to the tasks package and forgetting to update convert.go; plugins or forks introducing custom predicates; version mismatch where one package was regenerated/extended but the other not.

Related errors


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