usestrix/strix · error · SystemExit
Viewer UI is not built.\nBuild it with: cd strix/interface/v
Error message
Viewer UI is not built.\nBuild it with: cd strix/interface/viewer/frontend && npm ci && npm run build
What it means
SystemExit(1) with 'Viewer UI is not built' raised by the viewer CLI (strix/interface/viewer/cli.py main()) when bundle_is_built() reports the frontend asset bundle is missing. The viewer serves a pre-built JS/CSS bundle from strix/interface/viewer/frontend; when the package was installed from source without building the frontend, serving is impossible, so the CLI exits with the exact build command to run.
Source
Thrown at strix/interface/viewer/cli.py:63
default=0,
help="Port to serve on (default: an available ephemeral port).",
)
parser.add_argument("--host", default="127.0.0.1", help=argparse.SUPPRESS)
parser.add_argument(
"--no-open",
action="store_true",
help="Do not open the browser automatically.",
)
args = parser.parse_args(argv)
console = Console()
if not bundle_is_built():
console.print(
"[bold red]Viewer UI is not built.[/]\n"
"Build it with: [cyan]cd strix/interface/viewer/frontend && npm ci && npm run build[/]"
)
raise SystemExit(1)
run_dir = _resolve_run_dir(args.run, console)
httpd, url, token = serve(
run_dir,
host=args.host,
port=args.port,
open_browser=not args.no_open,
)
# The tokened URL is what authorizes the browser (steering, report sending,
# history). Print it rather than the bare URL so the operator -- and only
# the operator -- can open or share an authorized link.
open_url = authorized_url(url, token)
run_name = run_dir.name
summary = read_run_summary(run_dir)
live = not summary.get("finished", False)
View on GitHub (pinned to 8551339130)
Solutions
- Run the exact command shown: cd strix/interface/viewer/frontend && npm ci && npm run build (requires Node.js/npm installed)
- If Node is missing, install it first (e.g. via nvm or system package manager), then re-run the build
- Use an official release wheel/PyPI install, which ships the pre-built bundle, instead of a source checkout
- In Dockerfiles, make the frontend build step fatal (set -e) so a broken build fails the image build instead of deferring to runtime
Example fix
# before (Dockerfile, silent failure) RUN cd strix/interface/viewer/frontend && npm ci && npm run build || true # after RUN cd strix/interface/viewer/frontend && npm ci && npm run build
Defensive patterns
Strategy: validation
Validate before calling
from strix.interface.viewer.bundle import bundle_is_built # adjust import to actual module
def assert_viewer_ready():
if not bundle_is_built():
raise SystemExit(
"Viewer UI missing. Run: cd strix/interface/viewer/frontend && npm ci && npm run build"
) Try / catch
try:
main(argv)
except SystemExit as e:
if e.code == 1 and not bundle_is_built():
subprocess.run(["npm", "ci"], cwd="strix/interface/viewer/frontend", check=True)
subprocess.run(["npm", "run", "build"], cwd="strix/interface/viewer/frontend", check=True)
main(argv)
else:
raise Prevention
- Build the frontend as part of source-setup: make dev-install or the documented npm command
- Install from release wheels when Node.js is unavailable
- Make npm build steps fatal (set -e / check=True) in Dockerfiles and CI
When it happens
Trigger: Running the viewer (e.g. `strix viewer` / python -m strix.interface.viewer.cli) from a source checkout or a wheel built without the frontend step. bundle_is_built() finds no dist bundle, prints the message, and raises SystemExit(1) before binding any port.
Common situations: Fresh git clone + `uv run strix ...` without building the frontend; CI installing the package with --no-build-isolation that skips the npm step; node/npm absent from the image so the optional frontend build silently skipped; downstream packagers (Debian, conda) shipping a Python-only build; npm ci failing midway in a Docker build and the error being ignored.
Related errors
- '{spec}' must land inside the workspace: use a relative dest
- '{spec}' has an empty destination path
- '{spec}' has an invalid destination path: {candidate}
- '{spec}' has a control character in its destination path
- '{source}' is not an existing file
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/551d957393e61818.
Report an issue: GitHub.