pola-rs/polars · error

creating extension types not allowed - try setting the…

Error message

creating extension types not allowed - try setting the environment variable POLARS_ALLOW_EXTENSION

What it means

Polars' Object/extension dtype stores arbitrary Rust values in an Arrow ExtensionArray. Because the on-disk/FFI layout of extension arrays is not guaranteed stable, creating them is gated behind an explicit opt-in: either the POLARS_ALLOW_EXTENSION environment variable is set or the POLARS_ALLOW_EXTENSION feature gate was compiled in. Without it, create_extension panics to prevent users from unknowingly producing data with unsafe/unsupported semantics.

Solutions

  1. Set the environment variable POLARS_ALLOW_EXTENSION=1 before running the program to opt in to extension type creation
  2. If you control the build, enable the compile-time POLARS_ALLOW_EXTENSION flag instead of the env var
  3. Avoid the object/extension dtype entirely and model the data with supported dtypes (struct, list, string)

Example fix

// before
let out = df.group_by(["k"])?.agg([col("obj").agg_list()]); // panics
// after
// in shell / process env:
std::env::set_var("POLARS_ALLOW_EXTENSION", "1");
let out = df.group_by(["k"])?.agg([col("obj").agg_list()]);
Defensive patterns

Strategy: validation

Validate before calling

if std::env::var("POLARS_ALLOW_EXTENSION").is_err() {
    std::env::set_var("POLARS_ALLOW_EXTENSION", "1"); // or avoid object dtype
}

Try / catch

let result = std::panic::catch_unwind(|| build_object_series());

Prevention

When it happens

Trigger: Any API that builds an ObjectChunked / PolarsExtension, e.g. calling agg_list or finish on a Series/ObjectChunked of a custom Rust type (via #[derive(PolarsObject)] types) while neither the compiled-in POLARS_ALLOW_EXTENSION flag nor the env var is present.

Common situations: Using polars' object dtype feature with custom structs in GroupBy aggregations, or after upgrading polars where the opt-in became mandatory; running in environments (tests, containers) where the env var was never set.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/7428141737b476de. Report an issue: GitHub.

Appendix: source

Thrown at crates/polars-core/src/chunked_array/object/extension/mod.rs:69

            (drop_fn)()
        }
    }
}

// https://stackoverflow.com/questions/28127165/how-to-convert-struct-to-u8d
// not entirely sure if padding bytes in T are initialized or not.
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
    std::slice::from_raw_parts((p as *const T) as *const u8, size_of::<T>())
}

/// Create an extension Array that can be sent to arrow and (once wrapped in [`PolarsExtension`] will
/// also call drop on `T`, when the array is dropped.
pub(crate) fn create_extension<I: Iterator<Item = Option<T>> + TrustedLen, T: Sized + Default>(
    iter: I,
) -> PolarsExtension {
    let env = "POLARS_ALLOW_EXTENSION";
    if !(POLARS_ALLOW_EXTENSION.load() || std::env::var(env).is_ok()) {
        panic!("creating extension types not allowed - try setting the environment variable {env}")
    }
    let t_size = size_of::<T>();
    let t_alignment = align_of::<T>();
    let n_t_vals = iter.size_hint().1.unwrap();

    let mut buf = Vec::with_capacity(n_t_vals * t_size);
    let mut validity = BitmapBuilder::with_capacity(n_t_vals);

    // when we transmute from &[u8] to T, T must be aligned correctly,
    // so we pad with bytes until the alignment matches
    let n_padding = (buf.as_ptr() as usize) % t_alignment;
    buf.extend(std::iter::repeat_n(0, n_padding));

    // transmute T as bytes and copy in buffer
    for opt_t in iter.into_iter() {
        match opt_t {
            Some(t) => {
                unsafe {

View on GitHub (pinned to fe841f959e)