pydantic/monty · error

failed to read

Error message

failed to read {}: {e}

What it means

The pydantic-monty-client build script syncs the pinned dist versions in packages/pydantic-monty/pyproject.toml from the Cargo workspace version. It panics with this message when fs::read_to_string on the pyproject.toml fails — the file is missing, unreadable, or the path is wrong at build time.

Solutions

  1. Restore packages/pydantic-monty/pyproject.toml (git checkout -- packages/pydantic-monty/pyproject.toml or a fresh clone)
  2. Verify the file path/permissions: ls -l packages/pydantic-monty/pyproject.toml
  3. If the metapackage moved, update the path constant in crates/monty-python/build.rs

Example fix

// before
$ cargo build -p pydantic-monty-client
panicked: failed to read packages/pydantic-monty/pyproject.toml: No such file or directory

// after
git checkout -- packages/pydantic-monty/pyproject.toml
cargo build -p pydantic-monty-client  # succeeds
Defensive patterns

Strategy: validation

Validate before calling

test -f packages/pydantic-monty/pyproject.toml || echo 'metapackage pyproject.toml missing'

Prevention

When it happens

Trigger: Running `cargo build`/`cargo publish` for crates/monty-python when packages/pydantic-monty/pyproject.toml does not exist, was deleted, moved, or is unreadable due to file permissions.

Common situations: Fresh checkout missing the metapackage directory; build run from a sparse/partial workspace; a refactor renamed packages/pydantic-monty; build executed in a container that copied only part of the repo.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/a848005945e6fb18. Report an issue: GitHub.

Appendix: source

Thrown at crates/monty-python/build.rs:46

    pyo3_build_config::use_pyo3_cfgs();
}

/// Rewrite the metapackage's `version` and its pins on this distribution and
/// `pydantic-monty-runtime` if any has drifted from the Cargo package version.
///
/// All three distributions are built from the same workspace and released
/// together — `pydantic-monty` exists only to install the other two, and the
/// worker rejects a client whose version differs — so the pins must be exact.
/// Unlike monty-js there is no lockfile to refresh afterwards: uv.lock records
/// no specifier for workspace-editable sources.
///
/// Uses the runtime `CARGO_PKG_VERSION` env var (not `env!()`) so that the build
/// script picks up version changes without needing to be recompiled.
fn sync_meta_pyproject(path: &Path) {
    let cargo_version = env::var("CARGO_PKG_VERSION").expect("CARGO_PKG_VERSION not set");
    let pin_version = cargo_version_to_pep440(&cargo_version);

    let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("failed to read {}: {e}", path.display()));

    let mut result = String::with_capacity(contents.len());
    let mut changed = false;
    // one count per entry of `PINNED_DISTS`, plus the `version = ` line
    let mut pins = [0usize; PINNED_DISTS.len()];
    let mut versions = 0usize;

    for line in contents.lines() {
        let synced = if let Some(index) = pinned_dist(line) {
            pins[index] += 1;
            // Preserve the presence/absence of the trailing comma (the last
            // entry in the dependencies array has none).
            let comma = if line.ends_with(',') { "," } else { "" };
            Cow::Owned(format!("    \"{}=={pin_version}\"{comma}", PINNED_DISTS[index]))
        } else if line.starts_with("version = \"") {
            versions += 1;
            Cow::Owned(format!("version = \"{pin_version}\""))
        } else {

View on GitHub (pinned to adc986b362)