risingwavelabs/risingwave · error · ParserError

BOTH, LEADING, or TRAILING

Error message

BOTH, LEADING, or TRAILING

What it means

Raised by `parse_trim_where` when parsing a TRIM expression's positioning keyword. After `TRIM(` the parser expects exactly one of BOTH, LEADING, or TRAILING when a positional specifier is present; any other token fails the dispatch and `.expect` produces 'BOTH, LEADING, or TRAILING'. It signals an invalid or missing TRIM modifier keyword.

Source

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

            trim_what = Some(Box::new(self.parse_expr()?));
        }
        self.expect_token(&Token::RParen)?;

        Ok(Expr::Trim {
            expr: Box::new(expr),
            trim_where,
            trim_what,
        })
    }

    pub fn parse_trim_where(&mut self) -> ModalResult<TrimWhereField> {
        dispatch! { peek(keyword);
            Keyword::BOTH => keyword.value(TrimWhereField::Both),
            Keyword::LEADING => keyword.value(TrimWhereField::Leading),
            Keyword::TRAILING => keyword.value(TrimWhereField::Trailing),
            _ => fail
        }
        .expect("BOTH, LEADING, or TRAILING")
        .parse_next(self)
    }

    /// Parses an array expression `[ex1, ex2, ..]`
    pub fn parse_array_expr(&mut self) -> ModalResult<Expr> {
        let mut expected_depth = None;
        let exprs = self.parse_array_inner(0, &mut expected_depth)?;
        Ok(Expr::Array(Array {
            elem: exprs,
            // Top-level array is named.
            named: true,
        }))
    }

    fn parse_array_inner(
        &mut self,
        depth: usize,
        expected_depth: &mut Option<usize>,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Use one of the supported keywords: BOTH, LEADING, or TRAILING, e.g. `TRIM(LEADING 'x' FROM col)`.
  2. If no positional keyword is needed, write `TRIM(col)` or `TRIM('x' FROM col)`.
  3. Map dialect-specific keywords (LEFT/RIGHT) to LEADING/TRAILING before running.

Example fix

// before
SELECT TRIM(LEFT '0' FROM code) FROM t;
// after
SELECT TRIM(LEADING '0' FROM code) FROM t;
Defensive patterns

Strategy: validation

Validate before calling

const TRIM_WHERE = new Set(['BOTH','LEADING','TRAILING']);
function validTrimWhere(kw) { return TRIM_WHERE.has(kw.toUpperCase()); }

Type guard

const isTrimWhere = (s) => typeof s === 'string' && ['BOTH','LEADING','TRAILING'].includes(s.toUpperCase());

Prevention

When it happens

Trigger: Parsing `TRIM(<bad-keyword> 'x' FROM col)` where the token after TRIM( is not BOTH/LEADING/TRAILING but is not a valid field either, e.g. `TRIM(LEFT 'x' FROM col)` or `TRIM(BOTHH 'x' FROM col)`.

Common situations: Queries ported from databases with nonstandard TRIM syntax (e.g. LEFT/RIGHT in some engines); typos in manually written TRIM calls; code generators emitting positional trim keywords from another dialect.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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