windmill-labs/windmill · error

Parquet S3 input requires the `parquet` feature to be enable

Error message

Parquet S3 input requires the `parquet` feature to be enabled on this build

What it means

The S3 object-store integration can decode Parquet input files into JSON arrays, but the decoder exists only when the backend is built with the `parquet` cargo feature. The feature-gated stub bails with this message when S3 file inputs of Parquet type are processed without the feature.

Source

Thrown at backend/windmill-object-store/src/lib.rs:1612

        let reader = builder.build().map_err(to_anyhow)?;

        let mut out: Vec<u8> = Vec::new();
        let mut writer = json::Writer::<_, JsonArray>::new(&mut out);
        for batch in reader {
            let batch = batch.map_err(to_anyhow)?;
            writer.write(&batch).map_err(to_anyhow)?;
        }
        writer.finish().map_err(to_anyhow)?;
        drop(writer);
        String::from_utf8(out).map_err(to_anyhow)
    })
    .await
    .map_err(to_anyhow)?
}

#[cfg(not(feature = "parquet"))]
pub async fn decode_parquet_bytes_to_json_array(_bytes: bytes::Bytes) -> anyhow::Result<String> {
    anyhow::bail!("Parquet S3 input requires the `parquet` feature to be enabled on this build")
}

/// Decode the bytes of a CSV file into a JSON array text using the first row as headers.
/// Same blocking-thread pattern as the parquet decoder.
#[cfg(feature = "parquet")]
pub async fn decode_csv_bytes_to_json_array(bytes: bytes::Bytes) -> anyhow::Result<String> {
    use datafusion::arrow::csv::ReaderBuilder;
    use std::io::Cursor;

    task::spawn_blocking(move || {
        let cursor = Cursor::new(bytes);
        // Two-pass: infer schema from the bytes, then build the reader. The infer step
        // rewinds the underlying reader for us.
        let (schema, _) = datafusion::arrow::csv::reader::Format::default()
            .with_header(true)
            .infer_schema(Cursor::new(&cursor.get_ref()[..]), Some(1024))
            .map_err(to_anyhow)?;

View on GitHub (pinned to e474e8803c)

Solutions

  1. Rebuild the backend with the parquet feature enabled (e.g. `cargo build --features parquet, ...`)
  2. Use the official Windmill image which ships the parquet feature
  3. Convert the input file to CSV or JSON and use that input type instead

Example fix

// before
cargo build
// after
cargo build --features parquet
Defensive patterns

Strategy: validation

Validate before calling

// check the file type before choosing the S3 input path
if file_extension == "parquet" && !cfg!(feature = "parquet") {
  return Err(anyhow!("parquet input unsupported in this build"));
}

Try / catch

match decode_parquet_bytes_to_json_array(bytes).await {
  Err(e) if e.to_string().contains("parquet` feature") =>
    eprintln!("use a parquet-enabled build or convert to CSV/JSON"),
  Err(e) => return Err(e.into()),
  Ok(json) => json,
}

Prevention

When it happens

Trigger: Processing an S3 input file in Parquet format (decode_parquet_bytes_to_json_array) on a backend built without `--features parquet`.

Common situations: Self-compiled backends using S3 resource file inputs in Parquet format; official images include the feature, source builds may not.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/b0d2fd28187d994c. Report an issue: GitHub.