risingwavelabs/risingwave · error · StrError

{0}

Error message

{0}

What it means

StrError is a thin wrapper in sqlparser's parser.rs that converts the parser's ParserError enum into a plain String-bearing std error via thiserror's #[error("{0}")]. It is thrown whenever SQL parsing fails and the error is carried as a string — the message is simply the tokenizer/parser error text.

Source

Thrown at src/sqlparser/src/parser.rs:55

const WEBHOOK_WAIT_FOR_PERSISTENCE: &str = "webhook.wait_for_persistence";
const WEBHOOK_IS_BATCHED: &str = "is_batched";

#[derive(Debug, Clone, PartialEq)]
pub enum ParserError {
    TokenizerError(String),
    ParserError(String),
}

impl ParserError {
    pub fn inner_msg(self) -> String {
        match self {
            ParserError::TokenizerError(s) | ParserError::ParserError(s) => s,
        }
    }
}

#[derive(Debug, thiserror::Error)]
#[error("{0}")]
pub struct StrError(pub String);

// Use `Parser::expected` instead, if possible
#[macro_export]
macro_rules! parser_err {
    ($($arg:tt)*) => {
        return Err(winnow::error::ErrMode::Backtrack(<winnow::error::ContextError as winnow::error::FromExternalError<_, _>>::from_external_error(
            &Parser::default(),
            $crate::parser::StrError(format!($($arg)*)),
        )))
    };
}

impl From<StrError> for winnow::error::ErrMode<winnow::error::ContextError> {
    fn from(e: StrError) -> Self {
        winnow::error::ErrMode::Backtrack(<winnow::error::ContextError as winnow::error::FromExternalError<_, _>>::from_external_error(
            &Parser::default(),
            e,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Read the wrapped message: it names the exact token/position the parser choked on
  2. Fix the SQL syntax or quoting at that position
  3. If the syntax is valid Postgres but unsupported, check RisingWave's supported SQL subset or use an explicit dialect
  4. For programmatic callers, validate/escape user input SQL before parsing

Example fix

// before
Parser::parse_sql(&GenericDialect{}, "SELCT * FROM t") // -> StrError("Expected ..., found: SELCT")
// after
Parser::parse_sql(&PostgreSqlDialect{}, "SELECT * FROM t")
Defensive patterns

Strategy: validation

Validate before calling

// Basic pre-parse sanity check (Rust):
fn looks_like_sql(input: &str) -> Result<(), String> {
    let t = input.trim();
    if t.is_empty() { return Err("empty SQL statement".into()); }
    if t.ends_with(';') && t.matches(';').count() > 1 && !input.contains(";") { return Err("multiple statements not supported".into()); }
    Ok(())
}

Try / catch

// Rust
match Parser::parse_sql(dialect, sql) {
    Ok(stmts) => stmts,
    Err(e) => {
        let msg: StrError = e.into(); // StrError displays the parser message
        return Err(format!("SQL parse failed: {msg}"));
    }
}

Prevention

When it happens

Trigger: Calling Parser::parse_sql / parse_expr (or RisingWave APIs that wrap them) with SQL that the tokenizer or grammar rejects; every parser_err!/expected failure can surface as StrError.

Common situations: Typos or unsupported syntax in DDL/DML; dialect mismatch (Postgres-only features vs supported subset); wrong quoting/escaping of identifiers or strings; passing non-SQL text to the parser.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/4e68bcdc661d7258. Report an issue: GitHub.