pbakaus/impeccable · error · Error
Live browser script part missing
Error message
Live browser script part missing: ${part.name} (${part.path}) What it means
Before the live server assembles its injected browser bundle, assertLiveBrowserScriptParts() (skill/scripts/live/browser-script-parts.mjs) verifies that every frozen part exists on disk: session-state (live-browser-session.js), dom-helpers (live-browser-dom.js), and browser-ui (live-browser.js), joined under the supplied scriptsDir. The first missing file throws with its part name and full path. (A falsy scriptsDir fails earlier in resolveLiveBrowserScriptParts with 'scriptsDir is required'.)
Solutions
- Look at the exact path in the error message and restore that file
- Refresh the whole impeccable skill install (or, in the repo, re-run bun run build / bun run build:release) so scripts/ ships all three parts from one version
- If embedding with a custom scriptsDir, copy live-browser-session.js, live-browser-dom.js, and live-browser.js into it
- Never mix helper versions: the parts list is frozen per release and must match the assembling server
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import {
resolveLiveBrowserScriptParts,
} from './live/browser-script-parts.mjs';
const parts = resolveLiveBrowserScriptParts(scriptsDir);
const missing = parts.filter((p) => !fs.existsSync(p.path)).map((p) => p.path);
if (missing.length) {
throw new Error(`incomplete skill install — missing: ${missing.join(', ')}`);
}
// Safe to assertLiveBrowserScriptParts(parts) and assemble now. Try / catch
try {
assertLiveBrowserScriptParts(parts);
} catch (err) {
if (err?.message?.startsWith('Live browser script part missing:')) {
// Install-level defect: refresh the skill/scripts dir; do not continue boot.
failFastWithReinstallHint(err.message);
}
throw err;
} Prevention
- Install or update the impeccable skill as a unit — never cherry-pick files out of scripts/
- After updates, verify the three part files exist in the scripts dir the server resolves
- In the repo, run the build after pulling so generated trees stay consistent with sources
When it happens
Trigger: Booting the live server (or calling assembleLiveBrowserScript via resolve+assert) with a scriptsDir that lacks one of the three part files — a partial skill install, a stale dist/ from before the bundle was split into parts, or an embedder passing a custom scriptsDir that only contains some files.
Common situations: Updating the skill but keeping the old scripts directory (new server expects parts the old tree doesn't have); submodule/npx installs that didn't materialize every file; running from a source checkout without building; a copied .claude/skills/impeccable/scripts that was trimmed.
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
- Authentication failed. The server token may have changed.
- ${cap.error}
- Could not download the impeccable engine v
- Could not write the impeccable engine v
- Download failed
AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18).
Data as JSON: /api/errors/c5b2314e6f171caf.
Report an issue: GitHub.
Appendix: source
Thrown at skill/scripts/live/browser-script-parts.mjs:24
export const LIVE_BROWSER_SCRIPT_PARTS = Object.freeze([
Object.freeze({ name: 'session-state', file: 'live-browser-session.js' }),
Object.freeze({ name: 'dom-helpers', file: 'live-browser-dom.js' }),
Object.freeze({ name: 'browser-ui', file: 'live-browser.js' }),
]);
export function resolveLiveBrowserScriptParts(scriptsDir, parts = LIVE_BROWSER_SCRIPT_PARTS) {
if (!scriptsDir) throw new Error('scriptsDir is required');
return parts.map((part, index) => ({
...part,
index,
path: path.join(scriptsDir, part.file),
}));
}
export function assertLiveBrowserScriptParts(parts, exists = fs.existsSync) {
for (const part of parts) {
if (!exists(part.path)) {
throw new Error(`Live browser script part missing: ${part.name} (${part.path})`);
}
}
return parts;
}
export function readLiveBrowserScriptParts(parts, readFile = (filePath) => fs.readFileSync(filePath, 'utf-8')) {
return parts.map((part) => ({
...part,
source: readFile(part.path),
}));
}
export function assembleLiveBrowserScript({
token,
port,
vocabulary,
commandPrefix = '/',
appRoot = null,View on GitHub (pinned to f88b2837a7)