PyO3/pyo3 · error

failed to parse PyO3 config

Error message

failed to parse PyO3 config

What it means

pyo3-build-config panics with this message when the collected PyO3 interpreter configuration (from cargo metadata / PYO3_* env vars / python detection) cannot be parsed into a valid InterpreterConfig during a build. It runs in the build-script phase, so the failure aborts compilation of any crate depending on pyo3 or pyo3-ffi.

Source

Thrown at pyo3-build-config/src/lib.rs:147

        }
    }
}

/// Loads the configuration determined from the build environment.
///
/// This function must be called from a build script, and requires a direct dependency on at
/// least one of `pyo3` or `pyo3-ffi`.
pub fn get() -> &'static InterpreterConfig {
    static CONFIG: LazyLock<InterpreterConfig> = LazyLock::new(get_inner);
    &CONFIG
}

#[track_caller]
fn get_inner() -> InterpreterConfig {
    let Some(interpreter_config) = InterpreterConfig::from_cargo_dep_env() else {
        panic!("`pyo3_build_config::get()` requires a direct dependency on `pyo3` or `pyo3-ffi`")
    };
    interpreter_config.expect("failed to parse PyO3 config")
}

/// Registers `pyo3`s config names as reachable cfg expressions.
///
/// - <https://github.com/rust-lang/cargo/pull/13571>
/// - <https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-check-cfg>
#[doc(hidden)]
pub fn print_expected_cfgs() {
    println!("cargo:rustc-check-cfg=cfg(Py_LIMITED_API)");
    println!("cargo:rustc-check-cfg=cfg(Py_GIL_DISABLED)");
    println!("cargo:rustc-check-cfg=cfg(PyPy)");
    println!("cargo:rustc-check-cfg=cfg(GraalPy)");
    println!("cargo:rustc-check-cfg=cfg(RustPython)");
    println!(
        r#"cargo:rustc-check-cfg=cfg(py_sys_config, values("Py_DEBUG", "Py_REF_DEBUG", "Py_TRACE_REFS", "COUNT_ALLOCS"))"#
    );

    // allow `Py_3_*` cfgs from the minimum supported version up to the

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Clear stale build artifacts: cargo clean, then rebuild so the build script re-detects Python
  2. Check PYO3_CONFIG_FILE contents against the documented format (implementation, version, shared, pointer width, build flags)
  3. Unset conflicting PYO3_* env vars (PYO3_PYTHON, PYO3_CONFIG_FILE) and let pyo3 auto-detect
  4. Ensure a direct dependency on pyo3 or pyo3-ffi exists in Cargo.toml
  5. Pin or update the pyo3 version to one compatible with your toolchain

Example fix

// before
export PYO3_CONFIG_FILE=my-custom-config  # hand-written, malformed
// after
unset PYO3_CONFIG_FILE
export PYO3_PYTHON=/usr/bin/python3.12
cargo clean && cargo build
Defensive patterns

Strategy: validation

Validate before calling

# in shell before building
if [ -n "$PYO3_CONFIG_FILE" ]; then
  cat "$PYO3_CONFIG_FILE"  # must match the documented 5+ line format
fi
python --version  # confirm the interpreter pyo3 will detect

Try / catch

// build-time panic, not catchable in Rust; fix env and retry
cargo clean && cargo build 2>&1 | grep -A5 'failed to parse PyO3 config'

Prevention

When it happens

Trigger: Calling pyo3_build_config::get() when InterpreterConfig::from_cargo_dep_env() returns an unparsable or malformed config — typically a corrupted or hand-edited config passed via the cargo dep env, or an invalid PYO3_CONFIG_FILE.

Common situations: Malformed PYO3_CONFIG_FILE, mismatched PYO3_PYTHON / cross-compilation env vars, stale cargo target caches after switching Python interpreters or pyo3 versions.

Understand the failure class

Related errors


AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05). Data as JSON: /api/errors/ba934e06008d1138. Report an issue: GitHub.