{"record":{"id":"24c623f5b53c0ee3","repo":"risingwavelabs/risingwave","slug":"unconsumed","errorCode":null,"errorMessage":"unconsumed `>>`","messagePattern":"unconsumed `>>`","errorType":"validation","errorClass":"UnconsumedShiftRight","httpStatus":null,"severity":"error","filePath":"src/sqlparser/src/parser_v2/data_type.rs","lineNumber":132,"sourceCode":"    )\n    .context(StrContext::Label(\"struct_data_type\"))\n    .parse_next(input)\n}\n\n/// Consume a data type definition.\n///\n/// The parser is the main entry point for data type parsing.\n///\n/// Note: in recursion, we should use `data_type_stateful` instead of `data_type`,\n/// otherwise the type parameter will recurse like `Stateful<Stateful<Stateful<...>>>`.\n/// Also note that we cannot use `Parser<'_>` directly to avoid misuse, because we need\n/// generics `<S>` to parameterize over `Parser<'_>` and `Stateful<Parser<'_>>`.\npub fn data_type<S>(input: &mut S) -> ModalResult<DataType>\nwhere\n    S: TokenStream,\n{\n    #[derive(Debug, thiserror::Error)]\n    #[error(\"unconsumed `>>`\")]\n    struct UnconsumedShiftRight;\n\n    with_state::<S, DataTypeParsingState, _, _, _>(terminated(\n        data_type_stateful,\n        trace(\"data_type_verify_state\", |input: &mut StatefulStream<S>| {\n            // If there is remaining `>`, we should fail.\n            if *input.state.remaining_close.borrow() > 0 {\n                Err(ErrMode::Cut(ContextError::from_external_error(\n                    input,\n                    UnconsumedShiftRight,\n                )))\n            } else {\n                Ok(())\n            }\n        }),\n    ))\n    .context(StrContext::Label(\"data_type\"))\n    .parse_next(input)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/sqlparser/src/parser_v2/data_type.rs#L114-L150","documentation":"Raised by the SQL parser's `data_type` entry point when, after parsing a data type, a stray `>>` (shift-right) token remains unconsumed. This happens when a user writes nested generic type parameters like `array<array<int>>` where the parser cannot merge the two `>` into valid closing brackets. It is a syntax-level sanity check at the end of type parsing.","triggerScenarios":"Calling `data_type()` on input whose type expression ends with consecutive closing brackets forming a `>>` token, e.g. `STRUCT<a ARRAY<INT>>` or `MAP<INT, ARRAY<VARCHAR>>` in a DDL/CAST context.","commonSituations":"Users writing deeply nested types copied from other SQL dialects (Postgres/Hive/Spark) that allow `>>` in type syntax; hand-written CREATE TABLE with nested collections; tooling that generates types programmatically without spacing.","solutions":["Insert a space between consecutive closing brackets: `ARRAY<ARRAY<INT> >` instead of `ARRAY<ARRAY<INT>>`.","Rewrite the type using a non-generic equivalent if the dialect supports it (e.g. nested struct helpers).","If you maintain the parser, split the `>>` token into two `>` tokens in the tokenizer or handle bracket merging in `data_type_verify_state`."],"exampleFix":"// before\nCREATE TABLE t (a STRUCT<v ARRAY<INT>>);\n// after\nCREATE TABLE t (a STRUCT<v ARRAY<INT> >);","handlingStrategy":"validation","validationCode":"fn has_double_gt_at_type_end(sql_type: &str) -> bool {\n    sql_type.trim_end().ends_with(\">\")\n        && sql_type.contains(\">>\")\n}\n// if has_double_gt_at_type_end(\"ARRAY<ARRAY<INT>>\") { insert space between brackets }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always put a space between consecutive `>` when nesting generic types.","Lint generated DDL for `>>` sequences inside type definitions.","Prefer dialects/tools that auto-space nested collection types."],"tags":["sql-parser","syntax-error","data-type"],"backgroundTag":"invalid-argument-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}