databendlabs/databend · error

failed to build jsonb object from map

Error message

failed to build jsonb object from map

What it means

cast_scalar_to_variant converts a Map scalar into a jsonb object by collecting key/value pairs and calling OwnedJsonb::build_object, expecting object construction to succeed. The panic fires when jsonb's build_object errors — typically when the resulting object exceeds jsonb format size limits or encoding fails internally.

Solutions

  1. Reduce map size before casting to VARIANT.
  2. Replace expect with error propagation returning a proper ErrorCode for map-to-jsonb build failures.
  3. Enforce a key/value size limit on maps destined for VARIANT conversion.

Example fix

// before
let owned_jsonb = OwnedJsonb::build_object(kvs.iter().map(|(k, v)| (k, RawJsonb::new(&v[..]))))
    .expect("failed to build jsonb object from map");
// after
let owned_jsonb = OwnedJsonb::build_object(kvs.iter().map(|(k, v)| (k, RawJsonb::new(&v[..]))))
    .map_err(|e| ErrorCode::BadArguments(format!("failed to build jsonb object: {e}")))?;
Defensive patterns

Strategy: fallback

Validate before calling

if serialized_size(kvs) > MAX_JSONB_OBJECT_SIZE {
    return Err(ErrorCode::BadArguments("map too large to cast to VARIANT"));
}

Try / catch

// Catch panics around cast if it cannot be changed:
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    cast_scalar_to_variant(v, tz, &mut buf, typ.as_ref());
}));
if result.is_err() { /* fail query gracefully or emit NULL variant */ }

Prevention

When it happens

Trigger: Casting a MAP scalar whose serialized size (keys plus values) exceeds jsonb build limits, or containing items that fail jsonb encoding; maps built from very large or deeply nested values.

Common situations: Casting large MAP(...) results or map_agg outputs to VARIANT/JSON in queries; wide maps from aggregation hitting the jsonb document size cap.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


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

Appendix: source

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

            let kv_col = KvPair::<AnyType, AnyType>::try_downcast_column(&col).unwrap();
            let mut kvs = BTreeMap::new();
            for (k, v) in kv_col.iter() {
                let key = match k {
                    ScalarRef::String(v) => v.to_string(),
                    ScalarRef::Number(v) => v.to_string(),
                    ScalarRef::Decimal(v) => v.to_string(),
                    ScalarRef::Boolean(v) => v.to_string(),
                    ScalarRef::Timestamp(v) => timestamp_to_string(v, tz).to_string(),
                    ScalarRef::Date(v) => date_to_string(v).to_string(),
                    _ => unreachable!(),
                };
                let mut val = vec![];
                cast_scalar_to_variant(v, tz, &mut val, typ.as_ref());
                kvs.insert(key, val);
            }
            let owned_jsonb =
                OwnedJsonb::build_object(kvs.iter().map(|(k, v)| (k, RawJsonb::new(&v[..]))))
                    .expect("failed to build jsonb object from map");
            buf.extend_from_slice(owned_jsonb.as_ref());
            return;
        }
        ScalarRef::Bitmap(b) => {
            jsonb::Value::Array(
                deserialize_bitmap(b)
                    .unwrap()
                    .iter()
                    .map(|x| x.into())
                    .collect(),
            )
            .write_to_vec(buf);
            return;
        }
        ScalarRef::Tuple(fields) => {
            let owned_jsonb = match table_data_type {
                Some(TableDataType::Tuple {
                    fields_name,

View on GitHub (pinned to 288d84d76e)