{"record":{"id":"6cf3046157dc499d","repo":"apache/iceberg","slug":"cannot-write-unsupported-term-term","errorCode":null,"errorMessage":"Cannot write unsupported term: ${term}","messagePattern":"Cannot write unsupported term: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java","lineNumber":250,"sourceCode":"    private String operationType(Expression.Operation op) {\n      return op.toString().replace('_', '-').toLowerCase(Locale.ROOT);\n    }\n\n    private void term(Term term) throws IOException {\n      if (term instanceof UnboundTransform) {\n        UnboundTransform<?, ?> transform = (UnboundTransform<?, ?>) term;\n        transform(transform.transform().toString(), transform.ref().name());\n        return;\n      } else if (term instanceof BoundTransform) {\n        BoundTransform<?, ?> transform = (BoundTransform<?, ?>) term;\n        transform(transform.transform().toString(), transform.ref().name());\n        return;\n      } else if (term instanceof Reference) {\n        gen.writeString(((Reference<?>) term).name());\n        return;\n      }\n\n      throw new UnsupportedOperationException(\"Cannot write unsupported term: \" + term);\n    }\n\n    private void transform(String transform, String name) throws IOException {\n      gen.writeStartObject();\n      gen.writeStringField(TYPE, TRANSFORM);\n      gen.writeStringField(TRANSFORM, transform);\n      gen.writeStringField(TERM, name);\n      gen.writeEndObject();\n    }\n  }\n\n  public static Expression fromJson(String json) {\n    return fromJson(json, null);\n  }\n\n  public static Expression fromJson(JsonNode json) {\n    return fromJson(json, null);\n  }","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java#L232-L268","documentation":"When serializing a predicate's term to JSON, ExpressionParser only knows how to write Transform-terminated terms and plain References; any other Term implementation hits this UnsupportedOperationException. It signals a term type the parser's JSON format cannot represent.","triggerScenarios":"Calling ExpressionParser.toJson on an expression whose predicate term is a custom or unexpected Term implementation (neither NamedReference-derived nor a transform).","commonSituations":"Custom expression extensions or third-party Term implementations; bugs where an internal term type (e.g. an unbound transform with no reference) is fed to the parser.","solutions":["Use only standard Iceberg terms (References, Transforms) in expressions you serialize.","Check the term's class in the cause of the failure and convert it to a Reference or standard transform before serializing.","If you need custom terms, serialize them with your own parser rather than ExpressionParser."],"exampleFix":"// before\nExpressionParser.toJson(Expressions.predicate(\"op\", customTerm, value)); // customTerm: unsupported Term\n// after\nUnboundTerm<?> ref = Expressions.ref(\"column_name\");\nExpressionParser.toJson(Expressions.predicate(\"op\", ref, value));","handlingStrategy":"type-guard","validationCode":"if (!(expr instanceof Predicate)) throw new IllegalArgumentException(\"only predicates are serializable\");\nTerm t = ((Predicate) expr).term();\nif (!(t instanceof Reference) && !(hasSupportedTransform(t))) throw new IllegalArgumentException(\"unsupported term: \" + t.getClass());","typeGuard":"boolean serializableTerm(Term t) { return t instanceof Reference || t instanceof UnboundTransform; }","tryCatchPattern":"try {\n  ExpressionParser.toJson(expr, gen);\n} catch (UnsupportedOperationException e) {\n  throw new IllegalArgumentException(\"expression contains a non-serializable term\", e);\n}","preventionTips":["Build expressions only with Expressions factory methods (standard references and transforms).","Avoid custom Term implementations when serializing with ExpressionParser.","Test round-trip toJson/fromJson for any custom expression construction."],"tags":["expressions","serialization","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}