{"record":{"id":"cd961580d5c4f776","repo":"temporalio/temporal","slug":"and-requires-at-least-2-predicates-got-v","errorCode":null,"errorMessage":"And requires at least 2 predicates, got %v","messagePattern":"And requires at least 2 predicates, got (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/predicates/and.go","lineNumber":18,"sourceCode":"package predicates\n\nimport (\n\t\"fmt\"\n)\n\ntype (\n\tAndImpl[T any] struct {\n\t\t// TODO: see if we can somehow order arbitrary predicats and store a sorted list\n\t\tPredicates []Predicate[T]\n\t}\n)\n\nfunc And[T any](\n\tpredicates ...Predicate[T],\n) Predicate[T] {\n\tif len(predicates) < 2 {\n\t\tpanic(fmt.Sprintf(\"And requires at least 2 predicates, got %v\", len(predicates)))\n\t}\n\n\tflattened := make([]Predicate[T], 0, len(predicates))\n\tfor _, p := range predicates {\n\t\tswitch p := p.(type) {\n\t\tcase *AndImpl[T]:\n\t\t\tflattened = appendPredicates(flattened, p.Predicates...)\n\t\tcase *UniversalImpl[T]:\n\t\t\tcontinue\n\t\tcase *EmptyImpl[T]:\n\t\t\treturn p\n\t\tdefault:\n\t\t\tflattened = appendPredicates(flattened, p)\n\t\t}\n\t}\n\n\tswitch len(flattened) {\n\tcase 0:","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/predicates/and.go#L1-L36","documentation":"The And() constructor in common/predicates builds an AND-composed Predicate from 2+ sub-predicates. It panics when fewer than 2 predicates are passed because an AND of 0 or 1 predicates is meaningless in this library's API contract (callers should use the single predicate directly).","triggerScenarios":"Calling And() or And(p) with zero or one Predicate arguments. e.g. And[int]() or And(isEven).","commonSituations":"Building predicates programmatically from a dynamically-sized slice that ends up empty or has a single element after filtering; copying an Or(...) call and accidentally leaving one argument.","solutions":["Pass at least 2 predicates to And","If only one predicate exists, return it directly instead of wrapping in And","If the input slice may be empty, return a no-op/true predicate or return an error before calling And"],"exampleFix":"// before\npred := predicates.And(items...)\n// after\nvar pred predicates.Predicate[int]\nswitch len(items) {\ncase 1:\n    pred = items[0]\ndefault:\n    pred = predicates.And(items...) // len >= 2 guaranteed by caller\n}","handlingStrategy":"validation","validationCode":"if len(preds) < 2 {\n    // handle: use preds[0] directly or a defined always-true predicate\n    return preds[0]\n}\npred := predicates.And(preds...)","typeGuard":null,"tryCatchPattern":"func safeAnd[T any](ps ...predicates.Predicate[T]) (p predicates.Predicate[T]) {\n    defer func() {\n        if recover() != nil { p = fallbackPredicate[T]() }\n    }()\n    return predicates.And(ps...)\n}","preventionTips":["Check len(predicates) before calling And","For single-predicate cases, use the predicate directly","When building from slices, handle the empty case explicitly"],"tags":["go","panic","predicates","argument-validation"],"backgroundTag":"insufficient-arguments-panic","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}