{"record":{"id":"ed651e73d3d6db19","repo":"apache/beam","slug":"unable-to-unparse-s-with-d-operands","errorCode":null,"errorMessage":"Unable to unparse %s with %d operands.","messagePattern":"Unable to unparse (.+?) with (.+?) operands\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/bigquery/BeamBigQuerySqlDialect.java","lineNumber":190,"sourceCode":"    // TIMESTAMP_ADD(timestamp_expression, INTERVAL int64_expression date_part)\n    int operandCount = call.operandCount();\n    if (operandCount == 2) {\n      // operand0: timestamp_expression\n      // operand1: SqlIntervalLiteral (INTERVAL int64_expression date_part)\n      super.unparseCall(writer, call, leftPrec, rightPrec);\n    } else if (operandCount == 3) {\n      // operand0: timestamp_expression\n      // operand1: int64_expression\n      // operand2: date_part\n      final SqlWriter.Frame frame = writer.startFunCall(call.getOperator().getName());\n      call.operand(0).unparse(writer, leftPrec, rightPrec);\n      writer.literal(\",\");\n      writer.literal(\"INTERVAL\");\n      call.operand(1).unparse(writer, leftPrec, rightPrec);\n      call.operand(2).unparse(writer, leftPrec, rightPrec);\n      writer.endFunCall(frame);\n    } else {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Unable to unparse %s with %d operands.\",\n              call.getOperator().getName(), operandCount));\n    }\n  }\n\n  private void unparseExtractFunctions(\n      SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) {\n    String funName = call.getOperator().getName();\n    int operandCount = call.operandCount();\n    SqlNode tz = null;\n\n    final SqlWriter.Frame frame = writer.startFunCall(\"EXTRACT\");\n    if (!funName.equals(\"$extract\") && (operandCount == 1 || operandCount == 2)) {\n      // EXTRACT(DATE/TIME/DATETIME FROM timestamp_expression [AT TIME ZONE tz])\n      // operand0: timestamp_expression\n      // operand1: tz (optional)\n      writer.literal(EXTRACT_FUNCTIONS.get(funName));","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/bigquery/BeamBigQuerySqlDialect.java#L172-L208","documentation":"BeamBigQuerySqlDialect.unparseFunctionsUsingInterval only knows how to unparse interval-function calls with exactly three operands (function name, first arg, INTERVAL qualifier). Any other operand count produces this IllegalArgumentException, naming the operator and the actual operand count.","triggerScenarios":"Unparsing a SQL call routed to unparseFunctionsUsingInterval (via unparseCall) whose operand count is not the expected 3 — e.g. a custom or Calcite-generated operator variant of an interval function with 2 or 4 operands.","commonSituations":"Using interval arithmetic forms the dialect doesn't model (unary interval expressions, extra precision modifiers); Calcite rewrites producing differently-shaped RexCall nodes before unparse; version mismatches between Calcite and Beam's dialect.","solutions":["Rewrite the query to use standard 3-operand interval function forms supported by the dialect","Simplify interval expressions to INTERVAL n UNIT literals","Extend BeamBigQuerySqlDialect.unparseFunctionsUsingInterval to handle the extra operand shapes"],"exampleFix":"// before (dialect-side)\nthrow new IllegalArgumentException(...);\n// after: handle 2-operand form\nif (operandCount == 2) { call.operand(1).unparse(writer, leftPrec, rightPrec); writer.endFunCall(frame); return; }","handlingStrategy":"validation","validationCode":"// before unparse\nif (call.getOperands().size() != 3) {\n  throw new IllegalArgumentException(\"interval function \" + call.getOperator().getName() + \" must have 3 operands for BigQuery dialect\");\n}","typeGuard":"boolean isThreeOperandInterval(RexCall call) { return call.getOperands().size() == 3; }","tryCatchPattern":"try {\n  dialect.unparseCall(writer, call, left, right);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Unable to unparse\")) { /* fall back to generic unparse */ }\n  throw e;\n}","preventionTips":["Keep interval function calls in the exact shape the dialect expects","Check Calcite plan output (explain) for rewritten nodes before pushing to BigQuery","Pin Calcite versions compatible with your Beam version"],"tags":["beam-sql","bigquery","sql-unparse","arity"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}