Skip to content

Runtime manifest error names a fallback path that was never searched for #3370

Description

@miguel-heygen

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions