{"record":{"id":"595c56c82f7cf1ff","repo":"temporalio/temporal","slug":"unknown-task-predicate-type-t","errorCode":null,"errorMessage":"unknown task predicate type: %T","messagePattern":"unknown task predicate type: %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/history/queues/convert.go","lineNumber":128,"sourceCode":"\t\treturn ToPersistenceEmptyPredicate(predicate)\n\tcase *predicates.AndImpl[tasks.Task]:\n\t\treturn ToPersistenceAndPredicate(predicate)\n\tcase *predicates.OrImpl[tasks.Task]:\n\t\treturn ToPersistenceOrPredicate(predicate)\n\tcase *predicates.NotImpl[tasks.Task]:\n\t\treturn ToPersistenceNotPredicate(predicate)\n\tcase *tasks.NamespacePredicate:\n\t\treturn ToPersistenceNamespaceIDPredicate(predicate)\n\tcase *tasks.TypePredicate:\n\t\treturn ToPersistenceTaskTypePredicate(predicate)\n\tcase *tasks.DestinationPredicate:\n\t\treturn ToPersistenceDestinationPredicate(predicate)\n\tcase *tasks.OutboundTaskGroupPredicate:\n\t\treturn ToPersistenceOutboundTaskGroupPredicate(predicate)\n\tcase *tasks.OutboundTaskPredicate:\n\t\treturn ToPersistenceOutboundTaskPredicate(predicate)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unknown task predicate type: %T\", predicate))\n\t}\n}\n\nfunc FromPersistencePredicate(\n\tpredicate *persistencespb.Predicate,\n) tasks.Predicate {\n\tswitch predicate.GetPredicateType() {\n\tcase enumsspb.PREDICATE_TYPE_UNIVERSAL:\n\t\treturn FromPersistenceUniversalPredicate(predicate.GetUniversalPredicateAttributes())\n\tcase enumsspb.PREDICATE_TYPE_EMPTY:\n\t\treturn FromPersistenceEmptyPredicate(predicate.GetEmptyPredicateAttributes())\n\tcase enumsspb.PREDICATE_TYPE_AND:\n\t\treturn FromPersistenceAndPredicate(predicate.GetAndPredicateAttributes())\n\tcase enumsspb.PREDICATE_TYPE_OR:\n\t\treturn FromPersistenceOrPredicate(predicate.GetOrPredicateAttributes())\n\tcase enumsspb.PREDICATE_TYPE_NOT:\n\t\treturn FromPersistenceNotPredicate(predicate.GetNotPredicateAttributes())\n\tcase enumsspb.PREDICATE_TYPE_NAMESPACE_ID:","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/service/history/queues/convert.go#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a case for the concrete predicate type in the type switch, delegating to a new ToPersistence... converter","Register the new PREDICATE_TYPE in enumsspb and regenerate proto code (make proto / make update-go-api)","Add a unit test in convert_test.go covering the new predicate round-trip","If using a vendored/older temporal, upgrade so the predicate type is supported"],"exampleFix":"// before\ndefault:\n    panic(fmt.Sprintf(\"unknown task predicate type: %T\", predicate))\n// after\ncase *tasks.MyNewPredicate:\n    return ToPersistenceMyNewPredicate(predicate)\ndefault:\n    panic(fmt.Sprintf(\"unknown task predicate type: %T\", predicate))","handlingStrategy":"type-guard","validationCode":"switch p.(type) {\ncase *tasks.AllPredicate, *tasks.AndPredicate, *tasks.OrPredicate, *tasks.NotPredicate, *tasks.DestinationPredicate, *tasks.OutboundTaskGroupPredicate, *tasks.OutboundTaskPredicate:\n    // safe to convert\n}\n","typeGuard":"func isConvertiblePredicate(p tasks.Predicate) bool {\n    switch p.(type) {\n    case *tasks.AllPredicate, *tasks.AndPredicate, *tasks.OrPredicate,\n        *tasks.NotPredicate, *tasks.DestinationPredicate,\n        *tasks.OutboundTaskGroupPredicate, *tasks.OutboundTaskPredicate:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"func safeToConvert(p tasks.Predicate) (out *persistencespb.Predicate) {\n    defer func() {\n        if r := recover(); r != nil {\n            out = nil\n        }\n    }()\n    out = queues.ToPersistencePredicate(p)\n    return\n}","preventionTips":["When adding a new tasks.Predicate implementation, grep for ToPersistencePredicate and update the type switch and tests","Add a round-trip test per predicate type in convert_test.go","Keep predicate enum types and converters in the same PR"],"tags":["go","panic","type-switch","serialization","history-service"],"backgroundTag":"unhandled-type-case","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}