{"record":{"id":"0e87144fd63bf07f","repo":"apache/beam","slug":"for-a-cycling-sequence-generator-both-start-and-end-must-be","errorCode":null,"errorMessage":"For a cycling sequence generator, both 'start' and 'end' must be specified.","messagePattern":"For a cycling sequence generator, both 'start' and 'end' must be specified\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/datagen/DataGeneratorRowFn.java","lineNumber":132,"sourceCode":"    }\n\n    if (\"sequence\".equalsIgnoreCase(kind)) {\n      if (!SqlTypeName.INT_TYPES.contains(sqlTypeName)) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"The 'sequence' generator for integers only supports integer types, but field '%s' is of type '%s'.\",\n                field.getName(), sqlTypeName));\n      }\n\n      JsonNode startNode = properties.path(\"fields.\" + fieldName + \".start\");\n      JsonNode endNode = properties.path(\"fields.\" + fieldName + \".end\");\n\n      if (startNode.isMissingNode() && endNode.isMissingNode()) {\n        return (index) -> index;\n      }\n\n      if (startNode.isMissingNode() || endNode.isMissingNode()) {\n        throw new IllegalArgumentException(\n            \"For a cycling sequence generator, both 'start' and 'end' must be specified.\");\n      }\n\n      long start = startNode.asLong(0L);\n      long end = endNode.asLong(Long.MAX_VALUE);\n\n      if (start > end) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"For sequence generator, 'start' (%d) cannot be greater than 'end' (%d).\",\n                start, end));\n      }\n      long cycleLength = end - start + 1;\n      switch (sqlTypeName) {\n        case INTEGER:\n          return (index) -> (int) (start + (index % cycleLength));\n        case SMALLINT:\n          return (index) -> (short) (start + (index % cycleLength));","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/datagen/DataGeneratorRowFn.java#L114-L150","documentation":"A sequence generator needs an explicit range to cycle over. If only one of 'fields.<name>.start' and 'fields.<name>.end' is provided (the other missing), the cycle bounds cannot be computed and an IllegalArgumentException is thrown. Note: if BOTH are missing, the generator falls back to using the row index.","triggerScenarios":"Setting fields.<name>.start without fields.<name>.end (or vice versa) with kind='sequence' on an integer datagen field.","commonSituations":"Partial copy-paste of TBLPROPERTIES JSON; someone removed the 'end' key assuming 'start' alone is an incrementing counter.","solutions":["Specify both 'fields.<name>.start' and 'fields.<name>.end' in the table properties.","Remove both keys if you want the default index-based generator.","If an ever-increasing counter is desired, omit both and use the returned index generator, or set a large 'end'."],"exampleFix":"// before\n'{\"fields\":{\"id\":{\"kind\":\"sequence\",\"start\":1}}}'\n// after\n'{\"fields\":{\"id\":{\"kind\":\"sequence\",\"start\":1,\"end\":100}}}'","handlingStrategy":"validation","validationCode":"JsonNode start = props.path(\"fields.\" + name + \".start\");\nJsonNode end = props.path(\"fields.\" + name + \".end\");\nif (start.isMissingNode() != end.isMissingNode()) {\n  throw new IllegalArgumentException(name + \": both start and end required\");\n}","typeGuard":null,"tryCatchPattern":"try { buildRowFn(props); } catch (IllegalArgumentException e) { /* add missing bound or remove both */ }","preventionTips":["Always emit start and end together when templating sequence configs.","Omit both keys when index-based generation is intended."],"tags":["beam-sql","datagen","missing-config"],"backgroundTag":"missing-required-config-field","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"}