apache/iceberg · error · UnsupportedOperationException

Cannot write unsupported term

Error message

Cannot write unsupported term: ${term}

What it means

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.

Solutions

  1. Use only standard Iceberg terms (References, Transforms) in expressions you serialize.
  2. Check the term's class in the cause of the failure and convert it to a Reference or standard transform before serializing.
  3. If you need custom terms, serialize them with your own parser rather than ExpressionParser.

Example fix

// before
ExpressionParser.toJson(Expressions.predicate("op", customTerm, value)); // customTerm: unsupported Term
// after
UnboundTerm<?> ref = Expressions.ref("column_name");
ExpressionParser.toJson(Expressions.predicate("op", ref, value));
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(expr instanceof Predicate)) throw new IllegalArgumentException("only predicates are serializable");
Term t = ((Predicate) expr).term();
if (!(t instanceof Reference) && !(hasSupportedTransform(t))) throw new IllegalArgumentException("unsupported term: " + t.getClass());

Type guard

boolean serializableTerm(Term t) { return t instanceof Reference || t instanceof UnboundTransform; }

Try / catch

try {
  ExpressionParser.toJson(expr, gen);
} catch (UnsupportedOperationException e) {
  throw new IllegalArgumentException("expression contains a non-serializable term", e);
}

Prevention

When it happens

Trigger: Calling ExpressionParser.toJson on an expression whose predicate term is a custom or unexpected Term implementation (neither NamedReference-derived nor a transform).

Common situations: 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.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/6cf3046157dc499d. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java:250

    private String operationType(Expression.Operation op) {
      return op.toString().replace('_', '-').toLowerCase(Locale.ROOT);
    }

    private void term(Term term) throws IOException {
      if (term instanceof UnboundTransform) {
        UnboundTransform<?, ?> transform = (UnboundTransform<?, ?>) term;
        transform(transform.transform().toString(), transform.ref().name());
        return;
      } else if (term instanceof BoundTransform) {
        BoundTransform<?, ?> transform = (BoundTransform<?, ?>) term;
        transform(transform.transform().toString(), transform.ref().name());
        return;
      } else if (term instanceof Reference) {
        gen.writeString(((Reference<?>) term).name());
        return;
      }

      throw new UnsupportedOperationException("Cannot write unsupported term: " + term);
    }

    private void transform(String transform, String name) throws IOException {
      gen.writeStartObject();
      gen.writeStringField(TYPE, TRANSFORM);
      gen.writeStringField(TRANSFORM, transform);
      gen.writeStringField(TERM, name);
      gen.writeEndObject();
    }
  }

  public static Expression fromJson(String json) {
    return fromJson(json, null);
  }

  public static Expression fromJson(JsonNode json) {
    return fromJson(json, null);
  }

View on GitHub (pinned to 86d9c8fc54)