PyO3/pyo3 · error

Invalid config that sets both target_abi and abi3.

Error message

Invalid config that sets both target_abi and abi3.

What it means

A PYO3_CONFIG_FILE may specify the ABI either via the legacy `abi3` flag or the newer `target_abi` field, but not both. from_reader rejects a config that sets both to avoid ambiguity about which ABI actually applies.

Source

Thrown at pyo3-build-config/src/impl_.rs:779

                    parse_value!(suppress_build_script_link_lines, value)
                }
                "extra_build_script_line" => {
                    extra_build_script_lines.push(value.to_string());
                }
                "python_framework_prefix" => parse_value!(python_framework_prefix, value),
                unknown => warn!("unknown config key `{}`", unknown),
            }
        }

        let version = version.ok_or("missing value for version")?;
        let implementation = implementation.unwrap_or(PythonImplementation::CPython);
        let flags_contains_free_threaded = if let Some(ref flags) = build_flags {
            flags.0.contains(&BuildFlag::Py_GIL_DISABLED)
        } else {
            false
        };
        let target_abi = if let Some(target_abi) = target_abi {
            ensure!(
                abi3.is_none(),
                "Invalid config that sets both target_abi and abi3."
            );
            target_abi
        } else if flags_contains_free_threaded {
            // This fires even if is_abi3() is True for backward compatibility reasons
            PythonAbiBuilder::new(implementation, version)
                .free_threaded()
                .finalize()?
        } else if abi3 == Some(true) {
            warn!("abi3 configuration file option is deprecated since pyo3 0.29, set target_abi instead");
            PythonAbiBuilder::new(implementation, version)
                .stable_abi(StableAbi::Abi3)
                .finalize()?
        } else {
            PythonAbiBuilder::new(implementation, version).finalize()?
        };

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Edit the config file and remove the `abi3` line, keeping `target_abi` (or vice versa)
  2. Regenerate the config file with the pyo3 tooling for your pyo3 version instead of hand-editing
  3. Verify with `python -m pyo3_build_config`-style tooling or the pyo3 docs which format your pyo3 version expects

Example fix

# pyo3-config.txt, before
abi3
target_abi=abi3-cp312
# after
target_abi=abi3-cp312
Defensive patterns

Strategy: validation

Validate before calling

// shell
grep -q '^abi3' "$PYO3_CONFIG_FILE" && grep -q '^target_abi' "$PYO3_CONFIG_FILE" && echo 'config sets both abi3 and target_abi — remove one'

Prevention

When it happens

Trigger: Hand-editing or tool-generating a pyo3 config file that contains both an `abi3` line and a `target_abi` line; merging config snippets or upgrading a config file from an older pyo3 format by adding target_abi without removing abi3.

Common situations: Manually migrating a config written for old pyo3 to the new format; copy-pasting example config files and combining sections; build tooling that appends target_abi unconditionally to a template that already contains abi3.

Related errors


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