{"record":{"id":"8e867155b5689abb","repo":"apache/iceberg","slug":"unsupported-operation-op","errorCode":null,"errorMessage":"Unsupported operation: \" + op","messagePattern":"Unsupported operation: \" \\+ op","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java","lineNumber":373,"sourceCode":"        T value = literal(JsonUtil.get(VALUE, node), convertValue);\n        return Expressions.predicate(op, term, ImmutableList.of(value));\n      case IN:\n      case NOT_IN:\n        // literal set predicates\n        Preconditions.checkArgument(\n            node.has(VALUES), \"Cannot parse %s predicate: missing values\", op);\n        Preconditions.checkArgument(\n            !node.has(VALUE), \"Cannot parse %s predicate: has invalid value field\", op);\n        JsonNode valuesNode = JsonUtil.get(VALUES, node);\n        Preconditions.checkArgument(\n            valuesNode.isArray(), \"Cannot parse literals from non-array: %s\", valuesNode);\n        return Expressions.predicate(\n            op,\n            term,\n            Iterables.transform(\n                ((ArrayNode) valuesNode)::elements, valueNode -> literal(valueNode, convertValue)));\n      default:\n        throw new UnsupportedOperationException(\"Unsupported operation: \" + op);\n    }\n  }\n\n  private static <T> T literal(JsonNode valueNode, Function<JsonNode, T> toValue) {\n    if (valueNode.isObject() && valueNode.has(TYPE)) {\n      String type = JsonUtil.getString(TYPE, valueNode);\n      Preconditions.checkArgument(\n          type.equalsIgnoreCase(LITERAL), \"Cannot parse type as a literal: %s\", type);\n      return toValue.apply(JsonUtil.get(VALUE, valueNode));\n    }\n\n    // the node is a directly embedded literal value\n    return toValue.apply(valueNode);\n  }\n\n  private static Object asObject(JsonNode node) {\n    if (node.isIntegralNumber() && node.canConvertToLong()) {\n      return node.asLong();","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java#L355-L391","documentation":"While deserializing a predicate from JSON, ExpressionParser maps the JSON \"op\" string to an Expression.Operation; if the operation string is not one the parser recognizes (outside the supported set in its switch), it throws UnsupportedOperationException. This means the JSON was produced by a newer Iceberg version or hand-edited with an invalid op value.","triggerScenarios":"ExpressionParser.fromJson on JSON whose predicate operation string is not a known Expression.Operation name — forward-compatibility gap or manual JSON editing.","commonSituations":"Reading expression JSON written by a newer Iceberg release that added operations; corrupted or hand-written metadata files.","solutions":["Upgrade the Iceberg library to a version that supports the operation string in the JSON.","Validate the op string against Expression.Operation names before parsing.","Regenerate the JSON from a supported Iceberg version rather than hand-editing."],"exampleFix":"// before\nExpression parsed = ExpressionParser.fromJson(JsonUtil.parseJson(json));\n// after\nString op = JsonUtil.getString(\"op\", predNode);\nif (!isKnownOperation(op)) {\n  throw new IllegalArgumentException(\"unsupported op in expression JSON: \" + op);\n}\nExpression parsed = ExpressionParser.fromJson(JsonUtil.parseJson(json));","handlingStrategy":"validation","validationCode":"String op = JsonUtil.getString(\"op\", predNode);\nif (Stream.of(Expression.Operation.values()).noneMatch(o -> o.toString().equals(op))) {\n  throw new IllegalArgumentException(\"unknown predicate op: \" + op);\n}","typeGuard":null,"tryCatchPattern":"try {\n  Expression e = ExpressionParser.fromJson(node);\n} catch (UnsupportedOperationException e) {\n  LOG.error(\"unsupported op in expression JSON (library upgrade needed?)\", e);\n  throw e;\n}","preventionTips":["Keep the Iceberg version at or above the version that wrote the expression JSON.","Do not hand-edit expression JSON; regenerate via toJson.","Validate op strings against Expression.Operation before parsing."],"tags":["expressions","json","deserialization","forward-compatibility"],"backgroundTag":"invalid-enum-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}