{"record":{"id":"660dc0c1dabc845b","repo":"heygen-com/hyperframes","slug":"no-composition-found-in-dir","errorCode":null,"errorMessage":"No composition found in ${dir}","messagePattern":"No composition found in (.+?)","errorType":"validation","errorClass":"InvalidProjectError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/project.ts","lineNumber":52,"sourceCode":"): ProjectDir {\n  const trimmed = dirArg?.trim();\n  if (trimmed === \"#\") {\n    throw new InvalidProjectError(\n      \"Invalid project directory: #\",\n      \"# is a URL fragment, not a project path.\",\n      \"Run hyperframes preview . from your project directory.\",\n    );\n  }\n\n  const dir = resolve(dirArg ?? \".\");\n  const name = basename(dir);\n  const indexPath = resolve(dir, \"index.html\");\n\n  if (!existsSync(dir) || !statSync(dir).isDirectory()) {\n    throw new InvalidProjectError(\"Not a directory: \" + dir);\n  }\n  if (options.requireIndex !== false && !existsSync(indexPath)) {\n    throw new InvalidProjectError(\n      \"No composition found in \" + dir,\n      \"No index.html file found.\",\n      \"Run npx hyperframes init to create a new composition.\",\n    );\n  }\n\n  return { dir, name, indexPath };\n}\n\nexport function resolveProject(\n  dirArg: string | undefined,\n  options: ResolveProjectOptions = {},\n): ProjectDir {\n  try {\n    return resolveProjectOrThrow(dirArg, options);\n  } catch (err) {\n    if (err instanceof InvalidProjectError) {\n      // Self-exit (not a throw) so the cli.ts wrapper never sees it — report","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/utils/project.ts#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run `npx hyperframes init` in the project directory to scaffold index.html.","If the composition file has a different name, rename it to index.html (the convention this resolver expects).","Point the command at the subdirectory that actually contains index.html.","If you intentionally have no index.html and are calling a read-only API, pass { requireIndex: false }."],"exampleFix":"# before: empty / wrong directory\nhyperframes preview ./assets   # no index.html here\n# after\nnpx hyperframes init            # creates index.html\nhyperframes preview .","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nfunction ensureHasIndex(dirArg: string | undefined): void {\n  const dir = resolve(dirArg ?? '.');\n  if (!existsSync(resolve(dir, 'index.html'))) {\n    throw new Error(`No index.html in ${dir}. Run: npx hyperframes init`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return resolveProjectOrThrow(dirArg);\n} catch (err) {\n  if (err instanceof InvalidProjectError && /No composition found/.test(err.message)) {\n    // scaffold then retry\n    await runInit(dirArg);\n    return resolveProjectOrThrow(dirArg);\n  }\n  throw err;\n}","preventionTips":["Run `npx hyperframes init` once to scaffold index.html in every new project.","Name the entry file index.html (the convention this resolver enforces).","For read-only APIs that don't need a composition, pass { requireIndex: false }."],"tags":["cli","project","composition","init","filesystem"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}