{"record":{"id":"adc694b6c484836b","repo":"perspective-dev/perspective","slug":"labextension-is-not-present-in-data-directory-ple","errorCode":null,"errorMessage":"labextension is not present in data directory, please build `perspective-jupyterlab`","messagePattern":"labextension is not present in data directory, please build `perspective-jupyterlab`","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"rust/perspective-python/build.mjs","lineNumber":130,"sourceCode":"if (build_sdist) {\n    // `maturin sdist` has some issues with Cargo workspaces, so we assemble the sdist by hand here\n    // Note that the resulting sdist is _not_ a Cargo workspace, it is rooted in this package.\n    const cargo_toml = fs.readFileSync(\"./Cargo.toml\").toString(\"utf-8\");\n    const pyproject_toml = fs\n        .readFileSync(\"./pyproject.toml\")\n        .toString(\"utf-8\");\n\n    const cargo = toml.parse(cargo_toml);\n    const pyproject = toml.parse(pyproject_toml);\n    const version = cargo[\"package\"][\"version\"];\n    const data_dir = `perspective_python-${version}.data`;\n    const testfile = path.join(\n        data_dir,\n        \"data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json\",\n    );\n\n    if (!fs.existsSync(testfile)) {\n        throw new Error(\n            \"labextension is not present in data directory, please build `perspective-jupyterlab`\",\n        );\n    }\n\n    if (\n        !fs.existsSync(\"perspective/widget/static/perspective-anywidget.js\")\n    ) {\n        throw new Error(\n            \"anywidget bundle is not present in perspective/widget/static, please build `@perspective-dev/anywidget`\",\n        );\n    }\n\n    const readme_md = fs.readFileSync(\"./README.md\");\n    const pkg_info = generatePkgInfo(pyproject, cargo, readme_md);\n    fs.writeFileSync(\"./PKG-INFO\", pkg_info);\n\n    // Maturin finds extra license files in the root of the source directory,\n    // then packages them into .dist-info in the wheel.  As of Nov 2024,","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/perspective-dev/perspective/blob/11c8238c0c9c0b9e490b5a6a2dc277afad1e980a/rust/perspective-python/build.mjs#L112-L148","documentation":"This build script for the perspective-python wheel verifies that the JupyterLab labextension artifact (@perspective-dev/jupyterlab package.json) was copied into the wheel data directory. It throws because the file is absent, meaning the perspective-jupyterlab frontend package was never built or its output was not staged into data_dir before this check at build.mjs:130.","triggerScenarios":"Running `node build.mjs` (or the Python build/pip install that invokes it) when `data_dir/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json` does not exist — typically the perspective-jupyterlab package was not built first or its dist output was not copied into the data directory.","commonSituations":"Cloning the monorepo and building perspective-python without first building the jupyterlab extension; running a partial/clean build; CI caching that skips the frontend build; building only the python wheel target.","solutions":["Build the jupyterlab extension first: run the perspective-jupyterlab package's build (e.g. `pnpm build` in packages/perspective-jupyterlab or the monorepo-wide build) before building perspective-python","Run the full monorepo build so all frontend artifacts are produced and staged, then rebuild the python wheel","Verify the labextension output exists at packages path and that build.mjs's copy step into data_dir ran (check for errors earlier in the build log)","If the artifact exists but is misplaced, ensure you run the build from the repository root as expected (relative path `data_dir/data/share/jupyter/...` depends on cwd)"],"exampleFix":"# before\n$ cd rust/perspective-python && node build.mjs\nError: labextension is not present in data directory...\n// after\n$ pnpm install && pnpm build   # builds all packages incl. perspective-jupyterlab\n$ cd rust/perspective-python && node build.mjs  # proceeds past the check","handlingStrategy":"validation","validationCode":"const labext = require('fs').existsSync('data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json');\nif (!labext) throw new Error('Build perspective-jupyterlab before building perspective-python');","typeGuard":null,"tryCatchPattern":"try { await buildPython(); } catch (e) { if (/labextension is not present/.test(e.message)) { console.error('Run `pnpm build` in perspective-jupyterlab first'); process.exit(1); } throw e; }","preventionTips":["Always run the full monorepo build before building the python wheel","Add a pre-build step in CI that asserts labextension artifacts exist","Keep frontend and python build steps ordered in your build pipeline","Build from the repository root so relative paths resolve"],"tags":["build","missing-artifact","jupyterlab"],"backgroundTag":"file-not-found","analyzedSha":"11c8238c0c9c0b9e490b5a6a2dc277afad1e980a","analyzedAt":"2026-09-09T00:35:19.377Z","contentChangedAt":"2026-09-09T00:35:19.377Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}