Skip to content

Windows installation completely broken — two independent bugs in build hook #320

Description

@vojvojtech

Environment

  • OS: Windows 11
  • Install command: uv tool install git+https://github.com/padak/keboola_agent_cli

Expected behaviour

Installation succeeds. If the React SPA cannot be built, the hook logs a warning and produces a wheel without the bundled UI — the CLI still works; only kbagent serve --ui is degraded.


Actual behaviour

The build crashes on Windows in all cases. There are two independent bugs — one for each possible state of npm on the machine. There is no working installation path on Windows.


Bug 1 — npm is installed

Root cause: The hook detects npm and calls:

subprocess.check_call(["npm", "ci", "--prefer-offline", "--no-audit", "--no-fund"], cwd=frontend_dir)

On Windows, npm is a batch file (npm.cmd). Python's subprocess with shell=False (the default) cannot execute .cmd files and raises FileNotFoundError. The except clause only catches CalledProcessError, so FileNotFoundError propagates and kills the build.

Error output:

[hatch:build-ui] no prebuilt dist found; running npm build
FileNotFoundError: [WinError 2] The system cannot find the file specified

Bug 2 — npm is not installed

Root cause: The hook correctly detects no npm, logs a warning, and returns early without creating _ui_dist/. However, pyproject.toml has an unconditional force-include:

[tool.hatch.build.targets.wheel.force-include]
"src/keboola_agent_cli/_ui_dist" = "keboola_agent_cli/_ui_dist"

Hatchling requires this path to exist regardless of whether the hook created it. Since the early return never creates the directory, the build crashes.

Error output:

[hatch:build-ui] WARNING: no prebuilt SPA and no `npm` on PATH; wheel will not bundle the UI.
FileNotFoundError: Forced include not found:
  ...\src\keboola_agent_cli\_ui_dist

Proposed fixes

Bug 1 — catch OSError (parent of FileNotFoundError) alongside CalledProcessError, or pass shell=True on Windows:

# option A — broaden the except clause
except (subprocess.CalledProcessError, OSError) as exc:

# option B — use shell on Windows
subprocess.check_call(
    ["npm", "ci", "--prefer-offline", "--no-audit", "--no-fund"],
    cwd=frontend_dir,
    shell=sys.platform == "win32",
)

Bug 2 — when skipping the npm build, create an empty _ui_dist/ directory before returning so hatchling's force-include always finds something:

# in hatch_build.py, before any early `return`
target.mkdir(parents=True, exist_ok=True)

The existing runtime error raised by kbagent serve --ui when no UI is bundled already handles the empty-directory case gracefully — no further changes needed there.


Impact

The one-liner install command in the README does not work on Windows at all. Every Windows user hits one of these two bugs — there is no path to a successful install.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions