risingwavelabs/risingwave · error

unsupported JSON number: {v}

Error message

unsupported JSON number: {v}

What it means

append_json_value converts a serde_json::Value into a Variant builder. For numbers it accepts i64/u64 and f64; any other JSON number form cannot be represented and the conversion bails with this message. `v` is formatted with the JSON value's Display.

Source

Thrown at src/common/src/types/variant.rs:624

    Ok(())
}

fn append_json_value(
    json: &serde_json::Value,
    builder: &mut impl VariantBuilderExt,
) -> anyhow::Result<()> {
    match json {
        serde_json::Value::Null => builder.append_value(ParquetVariant::Null),
        serde_json::Value::Bool(v) => builder.append_value(*v),
        serde_json::Value::Number(v) => {
            if let Some(v) = v.as_i64() {
                builder.append_value(v);
            } else if let Some(v) = v.as_u64() {
                builder.append_value(v);
            } else if let Some(v) = v.as_f64() {
                append_float64(v, builder);
            } else {
                bail!("unsupported JSON number: {v}");
            }
        }
        serde_json::Value::String(v) => builder.append_value(v.as_str()),
        serde_json::Value::Array(values) => {
            let mut list = builder
                .try_new_list()
                .context("failed to create variant list")?;
            for value in values {
                append_json_value(value, &mut list)?;
            }
            list.finish();
        }
        serde_json::Value::Object(fields) => {
            let mut object = builder
                .try_new_object()
                .context("failed to create variant object")?;
            for (field, value) in fields.iter().sorted_by(|a, b| a.0.cmp(b.0)) {
                let mut field_builder = ObjectFieldBuilder::new(field.as_str(), &mut object);

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure JSON numbers fit in i64/u64/f64 before conversion
  2. Pre-normalize oversized numbers to strings in the upstream JSON
  3. Round extreme values with serde_json's Number::from_f64 before appending

Example fix

// before
builder_from(n.clone())?; // may bail on big numbers
// after
if let Some(f) = n.as_f64() {
    if f.is_finite() { append_float64(f, builder); }
}
Defensive patterns

Strategy: validation

Validate before calling

fn json_number_supported(n: &serde_json::Number) -> bool {
    n.as_i64().is_some() || n.as_u64().is_some() || n.as_f64().map(|f| f.is_finite()).unwrap_or(false)
}

Type guard

fn is_supported_number(n: &serde_json::Number) -> bool {
    n.as_i64().is_some() || n.as_u64().is_some() || n.as_f64().is_some()
}

Try / catch

match append_json_value(&mut builder, &value, ty) {
    Ok(()) => (),
    Err(e) if e.to_string().starts_with("unsupported JSON number") => {
        builder.append_value(value.to_string().as_str()); // fall back to string
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing serde_json::Value::Number values that are neither as_i64, as_u64 nor as_f64 — in practice JSON numbers like arbitrary-precision/1e999 or NaN-like constructs, or calling from_json_value/append_datum_value on JSON parsed with the `arbitrary_precision` feature where as_* conversions fail.

Common situations: Ingesting JSON with huge integers (beyond u64) or extreme floats (inf) from Kafka/HTTP sources, or JSON parsed in arbitrary-precision mode.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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