{"record":{"id":"3dd9c1e1d49d8037","repo":"apache/iceberg","slug":"not-a-literal-predicate","errorCode":null,"errorMessage":"Not a literal predicate: ","messagePattern":"Not a literal predicate: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/BoundPredicate.java","lineNumber":58,"sourceCode":"  @Override\n  public BoundReference<?> ref() {\n    return term().ref();\n  }\n\n  public boolean isUnaryPredicate() {\n    return false;\n  }\n\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":40,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/BoundPredicate.java#L40-L69","documentation":"BoundPredicate is the base class for bound predicates; only BoundLiteralPredicate represents a comparison against a single literal. asLiteralPredicate() is a narrowing accessor that throws IllegalStateException when called on a predicate that is not a literal predicate (e.g. unary or set predicates). Call isLiteralPredicate() first to check before narrowing.","triggerScenarios":"Calling asLiteralPredicate() on a BoundPredicate whose concrete type is BoundUnaryPredicate or BoundSetPredicate, typically after binding an expression via Binder.bind() and iterating predicate nodes in a visitor.","commonSituations":"Custom expression visitors that rewrite or evaluate bound expressions and assume every bound predicate is a literal comparison; forgot to branch on isLiteralPredicate()/isSetPredicate()/isUnaryPredicate() first.","solutions":["Check predicate.isLiteralPredicate() before calling asLiteralPredicate()","Handle each predicate kind in order: isUnaryPredicate(), isLiteralPredicate(), isSetPredicate()","Bind the expression first with Binder.bind(schema, expr); unbound predicates are not literal predicates"],"exampleFix":"// before\nBoundLiteralPredicate<?> lit = (BoundLiteralPredicate) boundPred.asLiteralPredicate();\n// after\nif (boundPred.isLiteralPredicate()) {\n  BoundLiteralPredicate<?> lit = boundPred.asLiteralPredicate();\n}","handlingStrategy":"type-guard","validationCode":"if (!pred.isLiteralPredicate()) { throw new IllegalArgumentException(\"expected literal predicate, got \" + pred.op()); }","typeGuard":"function asLit(p) { return p.isLiteralPredicate() ? p.asLiteralPredicate() : null; }","tryCatchPattern":"try { lit = pred.asLiteralPredicate(); } catch (IllegalStateException e) { /* handle non-literal predicate */ }","preventionTips":["Always call isLiteralPredicate() before asLiteralPredicate()","Branch on isUnaryPredicate/isLiteralPredicate/isSetPredicate in visitors","Bind expressions before inspecting predicate types"],"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"}