influxdata/influxdb · error
Unexpected content in ValueExpr
Error message
Unexpected content in ValueExpr
What it means
`ValueExpr::replace_col` panics with unreachable!() when the wrapped expr is not an `Expr::BinaryExpr`. ValueExpr is a typed wrapper guaranteeing the inner expr is a BinaryExpr whose left side is the `_value` column (enforced by TryFrom<Expr>), so this only fires if the invariant was bypassed — e.g. a ValueExpr constructed via unsafe/private means or the struct definition changed.
Solutions
- Only create ValueExpr via TryFrom<Expr> / expr.try_into() and handle the Err variant instead of unwrapping into a bad ValueExpr
- Confirm the expr passed through try_from was not modified after conversion
- If you construct ValueExpr within the crate, reuse TryFrom rather than struct-literal initialization
- Replace the panic with an Option/Result return to make the invariant failure recoverable
Example fix
// before
let ve = ValueExpr { expr: some_expr }; // bypasses invariant
let rewritten = ve.replace_col("field");
// after
let ve = ValueExpr::try_from(some_expr)
.map_err(|_| anyhow::anyhow!("expr is not a _value binary expr"))?;
let rewritten = ve.replace_col("field"); Defensive patterns
Strategy: type-guard
Validate before calling
fn can_replace_col(expr: &Expr, value_col: &str) -> bool {
matches!(expr, Expr::BinaryExpr(b) if matches!(b.left.as_ref(), Expr::Column(c) if c.name == value_col))
} Type guard
fn as_value_expr(expr: Expr) -> Option<ValueExpr> {
ValueExpr::try_from(expr).ok()
} Try / catch
// Rust: conversion is fallible, handle Err instead of unwrapping
let ve = match ValueExpr::try_from(expr) {
Ok(ve) => ve,
Err(orig) => return Err(anyhow!("not a _value binary expr: {orig:?}")),
}; Prevention
- Always construct ValueExpr via TryFrom<Expr>, never via struct literal
- Do not mutate the inner expr after conversion
- Add debug_assert! in replace_col documenting the BinaryExpr invariant
- Keep Expr-building helpers close to the ValueExpr definition so invariants stay in sync
When it happens
Trigger: Calling replace_col on a ValueExpr whose internal expr was mutated or constructed outside TryFrom<Expr> (bypassing the `_value`-column BinaryExpr check), e.g. `ValueExpr { expr: col("a") }` via struct literal within the crate.
Common situations: Crate-internal refactors that construct ValueExpr directly instead of via try_from; tests hand-building ValueExpr; version changes altering Expr variants.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- at least one expr
- By the point that we're doing partitioning, we should've…
- Existing transaction for table should not exist
- mapped to out-of-bounds shard
- no time column in metadata statistics
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/508080735c9f2bac.
Report an issue: GitHub.
Appendix: source
Thrown at core/predicate/src/lib.rs:345
right: _,
}) = &expr
&& let Expr::Column(inner) = left.as_ref()
&& inner.name == VALUE_COLUMN_NAME
{
return Ok(Self { expr });
}
Err(expr)
}
}
impl ValueExpr {
/// Returns a new [`Expr`] with the reference to the `_value`
/// column replaced with the specified column name
pub fn replace_col(&self, name: &str) -> Expr {
if let Expr::BinaryExpr(BinaryExpr { left: _, op, right }) = &self.expr {
binary_expr(name.as_expr(), *op, right.as_ref().clone())
} else {
unreachable!("Unexpected content in ValueExpr")
}
}
}
impl From<ValueExpr> for Expr {
fn from(value_expr: ValueExpr) -> Self {
value_expr.expr
}
}
#[cfg(test)]
mod tests {
use super::*;
use data_types::{MAX_NANO_TIME, MIN_NANO_TIME};
use datafusion::prelude::{col, lit};
#[test]
fn test_default_predicate_is_empty() {View on GitHub (pinned to 06200ef96b)