perspective-dev/perspective · error · Error

anywidget bundle is not present in…

Error message

anywidget bundle is not present in perspective/widget/static, please build `@perspective-dev/anywidget`

What it means

The python build script requires the anywidget client bundle `perspective/widget/static/perspective-anywidget.js` to exist in the wheel's static assets. It throws because the @perspective-dev/anywidget package output was not built or not copied into perspective/widget/static before this check at build.mjs:138.

Solutions

  1. Build `@perspective-dev/anywidget` (pnpm build in that package, or run the monorepo-wide build) before building perspective-python
  2. Re-run the full workspace build so anywidget output is generated and copied into perspective/widget/static
  3. Check the build log for a failed or skipped copy step into perspective/widget/static and fix the root failure
  4. If the bundle exists elsewhere, confirm you invoke build.mjs from the correct working directory so the relative path resolves

Example fix

# before
$ cd rust/perspective-python && node build.mjs
Error: anywidget bundle is not present in perspective/widget/static...
// after
$ pnpm build  # from repo root; includes @perspective-dev/anywidget
$ cd rust/perspective-python && node build.mjs
Defensive patterns

Strategy: validation

Validate before calling

if (!require('fs').existsSync('perspective/widget/static/perspective-anywidget.js')) {
  throw new Error('Build @perspective-dev/anywidget before building perspective-python');
}

Try / catch

try { await buildPython(); } catch (e) { if (/anywidget bundle is not present/.test(e.message)) { console.error('Run the @perspective-dev/anywidget build first'); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: Building perspective-python when `perspective/widget/static/perspective-anywidget.js` is absent — i.e. the `@perspective-dev/anywidget` package was not built or its bundle was not copied into the widget static directory.

Common situations: Partial monorepo builds skipping the anywidget package; stale node_modules after version bumps; CI jobs building only the python target; cleaning static/ without rebuilding the frontend.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of perspective-dev/perspective@11c8238c0c (2026-09-09). Data as JSON: /api/errors/4f8c47271664f2c6. Report an issue: GitHub.

Appendix: source

Thrown at rust/perspective-python/build.mjs:138

    const cargo = toml.parse(cargo_toml);
    const pyproject = toml.parse(pyproject_toml);
    const version = cargo["package"]["version"];
    const data_dir = `perspective_python-${version}.data`;
    const testfile = path.join(
        data_dir,
        "data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json",
    );

    if (!fs.existsSync(testfile)) {
        throw new Error(
            "labextension is not present in data directory, please build `perspective-jupyterlab`",
        );
    }

    if (
        !fs.existsSync("perspective/widget/static/perspective-anywidget.js")
    ) {
        throw new Error(
            "anywidget bundle is not present in perspective/widget/static, please build `@perspective-dev/anywidget`",
        );
    }

    const readme_md = fs.readFileSync("./README.md");
    const pkg_info = generatePkgInfo(pyproject, cargo, readme_md);
    fs.writeFileSync("./PKG-INFO", pkg_info);

    // Maturin finds extra license files in the root of the source directory,
    // then packages them into .dist-info in the wheel.  As of Nov 2024,
    // Maturin does not yet support explicitly declaring `license-files` in
    // pyproject.toml.  See https://github.com/PyO3/maturin/pull/862
    // https://github.com/PyO3/maturin/issues/861
    const crate_files = glob.sync(Array.from(cargo["package"]["include"]));
    const wheel_dir = `../target/wheels`;
    fs.mkdirSync(wheel_dir, { recursive: true });
    await tar.create(
        {

View on GitHub (pinned to 11c8238c0c)