databendlabs/databend · error

failed to parse geojson to json value

Error message

failed to parse geojson to json value

What it means

After decoding EWKB to a GeoJSON string, `cast_scalar_to_variant` re-parses that string with `jsonb::parse_owned_jsonb_with_buf` and panics with `expect("failed to parse geojson to json value")` if parsing fails. This assumes `Ewkb::to_json()` always emits valid JSON.

Solutions

  1. Inspect the geometry for NaN/Infinity or out-of-range coordinates and clean/round-trip the data at ingest.
  2. Align the jsonb and wkb crate versions in the workspace (cargo update consistently) and rebuild.
  3. Reproduce with the failing geometry value and report upstream (wkb/jsonb crates) with the GeoJSON string that fails to parse.
  4. Patch the expect into a mapped ErrorCode to avoid a process panic on bad geo data.

Example fix

// before
jsonb::parse_owned_jsonb_with_buf(geom.as_bytes(), buf).expect("failed to parse geojson to json value");
// after
jsonb::parse_owned_jsonb_with_buf(geom.as_bytes(), buf)
    .map_err(|e| ErrorCode::Internal(format!("failed to parse geojson to json value: {e}")))?;
Defensive patterns

Strategy: validation

Validate before calling

// reject geometries with non-finite coordinates before casting
fn coords_finite(bytes: &[u8]) -> bool {
    bytes.chunks_exact(8).all(|c| {
        let v = f64::from_le_bytes(c.try_into().unwrap());
        v.is_finite()
    })
}

Type guard

fn geojson_parseable(geom_json: &str) -> bool { serde_json::from_str::<serde_json::Value>(geom_json).is_ok() }

Prevention

When it happens

Trigger: Casting a Geometry (or Geography, same pattern in the next branch) scalar to Variant where the EWKB decodes but the produced GeoJSON string cannot be parsed as JSONB — e.g. NaN/Infinity coordinates serialized invalidly, or a jsonb version whose parser rejects the emitted shape.

Common situations: Geometries with NaN/inf coordinates produced by upstream computation; mismatched jsonb crate versions between workspace members; exotic geometry types whose GeoJSON serialization regressed in the wkb/geo crates.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/7a7090d188c5ff83. Report an issue: GitHub.

Appendix: source

Thrown at src/query/expression/src/types/variant.rs:400

                        values
                            .iter()
                            .enumerate()
                            .map(|(i, bytes)| (format!("{}", i + 1), RawJsonb::new(bytes))),
                    )
                    .expect("failed to build jsonb object from tuple")
                }
            };
            buf.extend_from_slice(owned_jsonb.as_ref());
            return;
        }
        ScalarRef::Variant(bytes) => {
            buf.extend_from_slice(bytes);
            return;
        }
        ScalarRef::Geometry(bytes) => {
            let geom = Ewkb(bytes).to_json().expect("failed to decode wkb data");
            jsonb::parse_owned_jsonb_with_buf(geom.as_bytes(), buf)
                .expect("failed to parse geojson to json value");
            return;
        }
        ScalarRef::Geography(bytes) => {
            // todo: Implement direct conversion, omitting intermediate processes
            let geom = Ewkb(bytes.0).to_json().expect("failed to decode wkb data");
            jsonb::parse_owned_jsonb_with_buf(geom.as_bytes(), buf)
                .expect("failed to parse geojson to json value");
            return;
        }
        ScalarRef::Vector(scalar) => with_vector_number_type!(|NUM_TYPE| match scalar {
            VectorScalarRef::NUM_TYPE(vals) => {
                let items = cast_scalars_to_variants(
                    vals.iter()
                        .map(|n| ScalarRef::Number(NumberScalar::NUM_TYPE(*n))),
                    tz,
                    None,
                );
                let owned_jsonb = OwnedJsonb::build_array(items.iter().map(RawJsonb::new))

View on GitHub (pinned to 288d84d76e)