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
- Build `@perspective-dev/anywidget` (pnpm build in that package, or run the monorepo-wide build) before building perspective-python
- Re-run the full workspace build so anywidget output is generated and copied into perspective/widget/static
- Check the build log for a failed or skipped copy step into perspective/widget/static and fix the root failure
- 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
- Run the workspace-wide build (pnpm build) before python packaging
- Never clean perspective/widget/static without rebuilding anywidget
- Verify widget static artifacts in CI before packaging the wheel
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)