HarperFast / HarperFast/harper

Payload-deployed components are never reinstalled, so a broken install cannot recover

Open
#1,974 0 comments 0 reactions 0 assignees View on GitHub
area:components bug
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## Summary

A component deployed by **payload** gets exactly one dependency install — at deploy time — and never again. If that install fails or its `node_modules` is lost, nothing restores it. Restarts don't help, because boot-time installation never considers the component at all.

Observed on 5.1.x: a component's `node_modules` was destroyed by a failed install (see #1973). Every subsequent restart left it broken with `Cannot find module` at resource load, and no npm run was even attempted — the npm logs were unchanged across restarts.

## Why

`deployComponent` (`components/operations.js`) only writes an application entry to the root config when the request carries a package identifier:

```js
if (req.package) {
const applicationConfig = { package: req.package };
...
await configUtils.addConfig(req.project, applicationConfig);
}
```

A payload deploy has no `req.package`, so no entry is written. `installApplications()` iterates root-config entries that have a `package` property, so a payload-deployed component is never in that set — it isn't in `harper-application-lock.json` either. It's loaded from the components directory on every boot, but its dependencies are never verified or reinstalled.

So the install is effectively one-shot, with no integrity check and no recovery path, for a whole class of deploys.

## Possibly related, unverified

Even for root-config applications, `installApplication` early-returns on mere **existence** of the directory:

```js
await access(join(application.dirPath, 'node_modules'), constants.F_OK);
// -> "already has node_modules; skipping install"
```

Separately, something in boot creates `node_modules/harper` (a symlink to the installed Harper package) so components can import `harper`. In the case observed, `node_modules` was absent before restart and afterwards contained *only* that symlink.

If that symlink is created before the existence check runs, then an empty-but-present `node_modules` would satisfy the check and suppress a needed install. **I could not confirm this**, because for the component in question `installApplication` was never reached at all (per the root-config gap above). Flagging it as a hazard worth checking rather than a diagnosis — if real, it affects root-config apps too, and an existence check is the wrong test either way.

## Suggested direction

Make dependency state verifiable and repairable independent of how the component was deployed: record what was installed, check it at load, and reinstall when it doesn't match — rather than inferring "installed" from a directory existing. At minimum, payload-deployed components should be reachable by the same boot-time install path as package-identifier ones.

Related: #1973 (how the install gets destroyed), #1975 (why the breakage stays invisible).

---

🤖 Filed by Claude on behalf of @heskew

Contributor guide

Open the contributing guide

Research direction

Start in components/operations.js with deployComponent, then trace installApplications and installApplication and how harper-application-lock.json is used. Check the payload-deploy path and the node_modules existence check, including the possible harper symlink hazard. Done means payload-deployed components are included in boot-time dependency verification and can recover from a failed or missing install.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.