risingwavelabs/risingwave · error · UnconsumedShiftRight
unconsumed `>>`
Error message
unconsumed `>>`
What it means
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.
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`.
Example fix
// before CREATE TABLE t (a STRUCT<v ARRAY<INT>>); // after CREATE TABLE t (a STRUCT<v ARRAY<INT> >);
Defensive patterns
Strategy: validation
Validate before calling
fn has_double_gt_at_type_end(sql_type: &str) -> bool {
sql_type.trim_end().ends_with(">")
&& sql_type.contains(">>")
}
// if has_double_gt_at_type_end("ARRAY<ARRAY<INT>>") { insert space between brackets } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- precision must be in range
- column data type is incompatible with downstream SQL Server…
- is not supported in SQL Server
- date/time field
- failed to parse relation definition
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/24c623f5b53c0ee3.
Report an issue: GitHub.
Appendix: source
Thrown at src/sqlparser/src/parser_v2/data_type.rs:132
)
.context(StrContext::Label("struct_data_type"))
.parse_next(input)
}
/// Consume a data type definition.
///
/// The parser is the main entry point for data type parsing.
///
/// Note: in recursion, we should use `data_type_stateful` instead of `data_type`,
/// otherwise the type parameter will recurse like `Stateful<Stateful<Stateful<...>>>`.
/// Also note that we cannot use `Parser<'_>` directly to avoid misuse, because we need
/// generics `<S>` to parameterize over `Parser<'_>` and `Stateful<Parser<'_>>`.
pub fn data_type<S>(input: &mut S) -> ModalResult<DataType>
where
S: TokenStream,
{
#[derive(Debug, thiserror::Error)]
#[error("unconsumed `>>`")]
struct UnconsumedShiftRight;
with_state::<S, DataTypeParsingState, _, _, _>(terminated(
data_type_stateful,
trace("data_type_verify_state", |input: &mut StatefulStream<S>| {
// If there is remaining `>`, we should fail.
if *input.state.remaining_close.borrow() > 0 {
Err(ErrMode::Cut(ContextError::from_external_error(
input,
UnconsumedShiftRight,
)))
} else {
Ok(())
}
}),
))
.context(StrContext::Label("data_type"))
.parse_next(input)View on GitHub (pinned to 6469eb736d)