tinyhumansai/openhuman · error

expected one top-level folder under {}, found {n}: {:?}

Error message

expected one top-level folder under {}, found {n}: {:?}

What it means

A structural validation guard in the Node.js archive extractor: the extraction root contained more than one top-level directory (the count and directory list are interpolated into the message). Official Node tarballs contain exactly one `node-vX.Y.Z-<platform>` folder; multiple candidates mean the archive layout is unexpected or the extraction root was reused and accumulated stale entries. Rather than picking arbitrarily, the extractor fails and lists what it found.

Source

Thrown at src/openhuman/runtime/node/extractor.rs:153

        .collect::<Result<Vec<_>, _>>()
        .with_context(|| format!("reading entries of {}", extract_root.display()))?;

    // Stable order for deterministic logging.
    entries.sort_by_key(|e| e.file_name());

    let mut dirs: Vec<PathBuf> = entries
        .into_iter()
        .filter(|e| e.file_type().map(|t| t.is_dir()).unwrap_or(false))
        .map(|e| e.path())
        .collect();

    match dirs.len() {
        1 => Ok(dirs.pop().unwrap()),
        0 => Err(anyhow!(
            "expected one top-level folder under {}, found none",
            extract_root.display()
        )),
        n => Err(anyhow!(
            "expected one top-level folder under {}, found {n}: {:?}",
            extract_root.display(),
            dirs
        )),
    }
}

/// Atomically move `staged` into place at `final_dest`.
///
/// Strategy:
/// 1. If `final_dest` already exists, move it to a sibling `.old-<pid>`
///    path so we never lose a working install even if a later step fails.
/// 2. Rename `staged` -> `final_dest`. On the same filesystem this is a
///    single `rename(2)` and is atomic from the reader's perspective.
/// 3. Best-effort cleanup of the `.old-*` directory.
///
/// Returns the `final_dest` path on success.
pub async fn atomic_install(staged: &Path, final_dest: &Path) -> Result<PathBuf> {

View on GitHub (pinned to 7491200858)

Solutions

  1. Remove the extraction directory so it starts clean and re-extract
  2. Inspect the listed directories — stale artifacts from a prior extraction sharing the root are the usual cause
  3. If the archive itself contains multiple roots, the download may be wrong; clear the cache and re-download
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/openhuman/runtime/node/extractor.rs:153 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/46f99349f61dc429. Report an issue: GitHub.