Describe the bug
When the hyperframe runtime manifest cannot be found, the error names a single path that
was never expected to exist. It is the last-resort default, not a location anything
searched for meaningfully, so it sends people looking in the wrong place.
A user hit this through --docker and reported:
[HyperframeRuntimeLoader] Missing manifest at /usr/local/lib/core/dist/hyperframe.manifest.json
/usr/local/lib/core/dist/ is monorepo-shaped arithmetic — /usr/local/lib/node_modules/hyperframes/dist
minus three segments — and cannot exist in a global npm install. The file that was actually
missing is /usr/local/lib/node_modules/hyperframes/dist/hyperframe.manifest.json, which the
message never mentions.
Root cause
packages/producer/src/services/hyperframeRuntimeLoader.ts:36:
export function resolveHyperframeManifestPath(): string {
if (process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH) {
return process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH;
}
const candidates = [
SIBLING_MANIFEST_PATH,
...CWD_RELATIVE_MANIFEST_PATHS,
MODULE_RELATIVE_MANIFEST_PATH,
];
for (const candidate of candidates) {
if (existsSync(candidate)) return candidate;
}
return MODULE_RELATIVE_MANIFEST_PATH; // <- nothing was found; return the last one anyway
}
The caller (line 59) then reports Missing manifest at ${manifestPath}. So on total failure
the user is shown candidate #5 and told nothing about candidates #1 to #4.
Verification
Built the render image on linux/amd64 exactly as ensureDockerImage() does
(packages/cli/src/commands/render.ts:554) and rendered through it successfully — the
manifest is present at /usr/local/lib/node_modules/hyperframes/dist/hyperframe.manifest.json
and the sibling lookup hits. npm pack hyperframes@0.8.3 also ships
package/dist/hyperframe.manifest.json, so the published artifact is correct.
Deleting only that one file inside the otherwise-good image reproduces the reported string
exactly:
docker run --rm --entrypoint sh <image> -c \
"rm -f /usr/local/lib/node_modules/hyperframes/dist/hyperframe.manifest.json; hyperframes render /project ..."
-> Failed: [HyperframeRuntimeLoader] Missing manifest at /usr/local/lib/core/dist/hyperframe.manifest.json
Which confirms the message is produced by the fallback branch and identifies nothing about
the real cause.
Suggested fix
Hoist the candidate list so the resolver and the error message share one owner, and print
every path that was tried:
const MANIFEST_CANDIDATES = [
SIBLING_MANIFEST_PATH,
resolve(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
resolve(process.cwd(), "../core/dist/hyperframe.manifest.json"),
resolve(process.cwd(), "core/dist/hyperframe.manifest.json"),
MODULE_RELATIVE_MANIFEST_PATH,
];
and at the throw, list them plus cwd. Keep the env-override case on its own branch: when
PRODUCER_HYPERFRAME_MANIFEST_PATH is set the other candidates were never tried, so listing
them would be untrue.
Printing the first candidate is the part that matters. The reporter would have seen the
path inside their own container and looked at it.
Two cleanups this touches
A duplicate candidate. CWD_RELATIVE_MANIFEST_PATHS[0] (line 15) is
resolve(PRODUCER_DIR, "hyperframe.manifest.json") — byte-identical to
SIBLING_MANIFEST_PATH on line 7, and mislabelled as cwd-relative. The list checks the same
path twice.
A test that asserts on source text. hyperframeRuntimeLoader.test.ts:51 regexes the
source for const candidates = [...] and compares string indexes to check ordering:
const candidatesMatch = source.match(/const candidates = \[([\s\S]*?)\];/);
const siblingIdx = candidatesBody.indexOf("SIBLING_MANIFEST_PATH");
expect(siblingIdx).toBeLessThan(cwdIdx);
That breaks on any rename or refactor while never exercising the behaviour. Worth replacing
with the behaviour test this change makes possible: point
PRODUCER_HYPERFRAME_MANIFEST_PATH at a nonexistent file and assert the thrown message
names it.
Related: a hint shown inside the thing it suggests
Same failure path, packages/cli/src/commands/render.ts:902, attaches the hint
"Try --docker for containerized rendering" — which is printed to users who are already
inside the container. packages/cli/src/docker/Dockerfile.render:28 sets ENV CONTAINER=true,
and nothing in packages/cli/src currently reads process.env.CONTAINER, so suppressing the
hint on that variable is a one-line change.
Environment
hyperframes 0.8.3 / 0.8.4
Verified on linux/amd64, Docker 24.0.0-rc.2
Affected packages/producer/src/services/hyperframeRuntimeLoader.ts:36,49,59
packages/producer/src/services/hyperframeRuntimeLoader.test.ts:51
packages/cli/src/commands/render.ts:902
Describe the bug
When the hyperframe runtime manifest cannot be found, the error names a single path that
was never expected to exist. It is the last-resort default, not a location anything
searched for meaningfully, so it sends people looking in the wrong place.
A user hit this through
--dockerand reported:/usr/local/lib/core/dist/is monorepo-shaped arithmetic —/usr/local/lib/node_modules/hyperframes/distminus three segments — and cannot exist in a global npm install. The file that was actually
missing is
/usr/local/lib/node_modules/hyperframes/dist/hyperframe.manifest.json, which themessage never mentions.
Root cause
packages/producer/src/services/hyperframeRuntimeLoader.ts:36:The caller (line 59) then reports
Missing manifest at ${manifestPath}. So on total failurethe user is shown candidate #5 and told nothing about candidates #1 to #4.
Verification
Built the render image on linux/amd64 exactly as
ensureDockerImage()does(
packages/cli/src/commands/render.ts:554) and rendered through it successfully — themanifest is present at
/usr/local/lib/node_modules/hyperframes/dist/hyperframe.manifest.jsonand the sibling lookup hits.
npm pack hyperframes@0.8.3also shipspackage/dist/hyperframe.manifest.json, so the published artifact is correct.Deleting only that one file inside the otherwise-good image reproduces the reported string
exactly:
Which confirms the message is produced by the fallback branch and identifies nothing about
the real cause.
Suggested fix
Hoist the candidate list so the resolver and the error message share one owner, and print
every path that was tried:
and at the throw, list them plus
cwd. Keep the env-override case on its own branch: whenPRODUCER_HYPERFRAME_MANIFEST_PATHis set the other candidates were never tried, so listingthem would be untrue.
Printing the first candidate is the part that matters. The reporter would have seen the
path inside their own container and looked at it.
Two cleanups this touches
A duplicate candidate.
CWD_RELATIVE_MANIFEST_PATHS[0](line 15) isresolve(PRODUCER_DIR, "hyperframe.manifest.json")— byte-identical toSIBLING_MANIFEST_PATHon line 7, and mislabelled as cwd-relative. The list checks the samepath twice.
A test that asserts on source text.
hyperframeRuntimeLoader.test.ts:51regexes thesource for
const candidates = [...]and compares string indexes to check ordering:That breaks on any rename or refactor while never exercising the behaviour. Worth replacing
with the behaviour test this change makes possible: point
PRODUCER_HYPERFRAME_MANIFEST_PATHat a nonexistent file and assert the thrown messagenames it.
Related: a hint shown inside the thing it suggests
Same failure path,
packages/cli/src/commands/render.ts:902, attaches the hint"Try --docker for containerized rendering"— which is printed to users who are alreadyinside the container.
packages/cli/src/docker/Dockerfile.render:28setsENV CONTAINER=true,and nothing in
packages/cli/srccurrently readsprocess.env.CONTAINER, so suppressing thehint on that variable is a one-line change.
Environment
hyperframes 0.8.3 / 0.8.4 Verified on linux/amd64, Docker 24.0.0-rc.2 Affected packages/producer/src/services/hyperframeRuntimeLoader.ts:36,49,59 packages/producer/src/services/hyperframeRuntimeLoader.test.ts:51 packages/cli/src/commands/render.ts:902