{"record":{"id":"e4e1a6c957c650c7","repo":"apache/iceberg","slug":"not-a-set-predicate","errorCode":null,"errorMessage":"Not a set predicate: ","messagePattern":"Not a set predicate: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/BoundPredicate.java","lineNumber":66,"sourceCode":"\n  public BoundUnaryPredicate<T> asUnaryPredicate() {\n    throw new IllegalStateException(\"Not a unary predicate: \" + this);\n  }\n\n  public boolean isLiteralPredicate() {\n    return false;\n  }\n\n  public BoundLiteralPredicate<T> asLiteralPredicate() {\n    throw new IllegalStateException(\"Not a literal predicate: \" + this);\n  }\n\n  public boolean isSetPredicate() {\n    return false;\n  }\n\n  public BoundSetPredicate<T> asSetPredicate() {\n    throw new IllegalStateException(\"Not a set predicate: \" + this);\n  }\n}\n","sourceCodeStart":48,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/BoundPredicate.java#L48-L69","documentation":"BoundSetPredicate represents IN/NOT_IN predicates over a set of literals; asSetPredicate() is the narrowing accessor for it. The base BoundPredicate throws IllegalStateException here because most bound predicates (comparisons, unary predicates) are not set predicates. Guard with isSetPredicate() before calling.","triggerScenarios":"Calling asSetPredicate() on a BoundPredicate that is actually a BoundLiteralPredicate or BoundUnaryPredicate, e.g. when collecting IN clause literals from a bound expression without checking the predicate kind.","commonSituations":"Scan-planning or partition-pruning code that extracts IN-set values from filter expressions but encounters a simple == or IS NULL predicate instead.","solutions":["Check predicate.isSetPredicate() before calling asSetPredicate()","Branch on predicate kind before accessing set-specific state","Ensure the expression was bound with Binder.bind; binding normalizes single-element IN into literal predicates"],"exampleFix":"// before\nBoundSetPredicate<?> set = boundPred.asSetPredicate();\n// after\nif (boundPred.isSetPredicate()) {\n  BoundSetPredicate<?> set = boundPred.asSetPredicate();\n}","handlingStrategy":"type-guard","validationCode":"if (!pred.isSetPredicate()) { throw new IllegalArgumentException(\"expected set predicate, got \" + pred.op()); }","typeGuard":"function asSet(p) { return p.isSetPredicate() ? p.asSetPredicate() : null; }","tryCatchPattern":"try { set = pred.asSetPredicate(); } catch (IllegalStateException e) { /* handle non-set predicate */ }","preventionTips":["Check isSetPredicate() before extracting IN-set literals","Handle literal and unary predicate cases alongside set predicates","Remember binding collapses single-element IN to a literal predicate"],"tags":["expressions","predicate-narrowing","illegal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}