heygen-com/hyperframes · error · InvalidProjectError

No composition found in ${dir}

Error message

No composition found in ${dir}

What it means

resolveProjectOrThrow: the directory exists and is a directory, but index.html is not inside it (existsSync(indexPath) false) and options.requireIndex !== false. Every hyperframes composition is rooted at index.html; without it there is no composition to preview/render/publish. Thrown as InvalidProjectError with hint 'No index.html file found.' and a suggestion to run init.

Source

Thrown at packages/cli/src/utils/project.ts:52

): ProjectDir {
  const trimmed = dirArg?.trim();
  if (trimmed === "#") {
    throw new InvalidProjectError(
      "Invalid project directory: #",
      "# is a URL fragment, not a project path.",
      "Run hyperframes preview . from your project directory.",
    );
  }

  const dir = resolve(dirArg ?? ".");
  const name = basename(dir);
  const indexPath = resolve(dir, "index.html");

  if (!existsSync(dir) || !statSync(dir).isDirectory()) {
    throw new InvalidProjectError("Not a directory: " + dir);
  }
  if (options.requireIndex !== false && !existsSync(indexPath)) {
    throw new InvalidProjectError(
      "No composition found in " + dir,
      "No index.html file found.",
      "Run npx hyperframes init to create a new composition.",
    );
  }

  return { dir, name, indexPath };
}

export function resolveProject(
  dirArg: string | undefined,
  options: ResolveProjectOptions = {},
): ProjectDir {
  try {
    return resolveProjectOrThrow(dirArg, options);
  } catch (err) {
    if (err instanceof InvalidProjectError) {
      // Self-exit (not a throw) so the cli.ts wrapper never sees it — report

View on GitHub (pinned to c2996c8626)

Solutions

  1. Run `npx hyperframes init` in the project directory to scaffold index.html.
  2. If the composition file has a different name, rename it to index.html (the convention this resolver expects).
  3. Point the command at the subdirectory that actually contains index.html.
  4. If you intentionally have no index.html and are calling a read-only API, pass { requireIndex: false }.

Example fix

# before: empty / wrong directory
hyperframes preview ./assets   # no index.html here
# after
npx hyperframes init            # creates index.html
hyperframes preview .
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
import { resolve } from 'node:path';

function ensureHasIndex(dirArg: string | undefined): void {
  const dir = resolve(dirArg ?? '.');
  if (!existsSync(resolve(dir, 'index.html'))) {
    throw new Error(`No index.html in ${dir}. Run: npx hyperframes init`);
  }
}

Try / catch

try {
  return resolveProjectOrThrow(dirArg);
} catch (err) {
  if (err instanceof InvalidProjectError && /No composition found/.test(err.message)) {
    // scaffold then retry
    await runInit(dirArg);
    return resolveProjectOrThrow(dirArg);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running a command on a directory that has not been initialized as a hyperframes project (no index.html); the entry file is named differently (main.html, composition.html) without being the conventional index.html; index.html was deleted or never created; the wrong directory was passed.

Common situations: Fresh directory where the user forgot `hyperframes init`; a project where the composition lives in a subfolder (e.g. src/) but the parent was passed; a renamed index file; an interrupted init that created folders but not the html.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/660dc0c1dabc845b. Report an issue: GitHub.