risingwavelabs/risingwave · error
invalid regular expression option
Error message
invalid regular expression option: "{c}" What it means
RisingWave parses a regex flags string character-by-character into `RegexpOptions` (case_insensitive, global, etc.). Any character other than the supported option letters is rejected with this error, since there is no silent-tolerance policy for unknown flags.
Solutions
- Use only supported flags: 'i' (case-insensitive), 'c' (case-sensitive), 'g' (global)
- Remove unsupported flags such as 'x', 's', 'n' from the flags string
- Rewrite the pattern to achieve the flag's effect (e.g. use (?s) inline constructs if supported by the regex crate)
Example fix
-- before SELECT regexp_replace(s, 'a', 'b', 'x'); -- after SELECT regexp_replace(s, 'a', 'b', 'g');
Defensive patterns
Strategy: validation
Validate before calling
const ok = /^[icg]*$/.test(flags); if (!ok) throw new Error(`unsupported regex flags: ${flags}`); Try / catch
try { await rw.query(sql) } catch (e) { if (String(e).includes('invalid regular expression option')) { /* sanitize flags and retry */ } else throw e; } Prevention
- Restrict flags to i, c, g when generating SQL
- Sanitize user-supplied flags before interpolation
- Avoid porting engine-specific flags (x, s, n) directly
When it happens
Trigger: Passing a flags string to any regex function (regexp_match/replace/count/etc., or `RegexpOptions::from_str`) containing an unsupported character, e.g. 'x' (extended), 's', 'm' (multiline is 'm'? — only supported single-char options pass), or whitespace/typos.
Common situations: Porting regex flags from other engines (Postgres 'ng', PCRE 'x', JS 's'), typos like 'gg' or accidental spaces in the flag literal.
Understand the failure class
Background: "unknown output mode", "invalid value for flag", "expects true/false": fixing invalid flag value errors in CLI tools — this error's family across 24 libraries.
Related errors
- regexp_count() does not support the global option
- {0}
- {0}
- AFTER MATCH SKIP TO FIRST/LAST missing its target variable
- ALTER SINK_RATE_LIMIT is not for sink into table
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/8eb3ca1d2bd8a077.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/scalar/regexp.rs:129
/// `g`
global: bool,
}
impl FromStr for RegexpOptions {
type Err = ExprError;
fn from_str(s: &str) -> Result<Self> {
let mut opts = Self::default();
for c in s.chars() {
match c {
// Case sensitive matching here
'c' => opts.case_insensitive = false,
// Case insensitive matching here
'i' => opts.case_insensitive = true,
// Global matching here
'g' => opts.global = true,
_ => {
bail!("invalid regular expression option: \"{c}\"");
}
}
}
Ok(opts)
}
}
#[function(
// source ~ pattern
"regexp_eq(varchar, varchar) -> boolean",
prebuild = "RegexpContext::from_pattern($1)?"
)]
fn regexp_eq(text: &str, regex: &RegexpContext) -> bool {
regex.regex.is_match(text).unwrap()
}
#[function(
// regexp_match(source, pattern)View on GitHub (pinned to 6469eb736d)