{"record":{"id":"aff89b5a3e9689c1","repo":"heygen-com/hyperframes","slug":"not-a-directory-dir","errorCode":null,"errorMessage":"Not a directory: ${dir}","messagePattern":"Not a directory: (.+?)","errorType":"validation","errorClass":"InvalidProjectError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/project.ts","lineNumber":49,"sourceCode":"export function resolveProjectOrThrow(\n  dirArg: string | undefined,\n  options: ResolveProjectOptions = {},\n): 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);","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/utils/project.ts#L31-L67","documentation":"resolveProjectOrThrow: the resolved path (dirArg ?? '.', made absolute via resolve()) either does not exist (existsSync false) or exists but is not a directory (statSync().isDirectory() false). This is the generic not-a-directory guard that fires for any bad path that is not the special '#' case. Thrown as InvalidProjectError with title 'Not a directory: <abs path>'.","triggerScenarios":"Passing a path to a file instead of a directory; a typo in the project path; a relative path resolved against an unexpected cwd; a path on a filesystem that is not mounted; a symlink loop or a broken symlink; passing '.' from a directory that itself was deleted.","commonSituations":"User runs `hyperframes render index.html` (file, not dir) instead of `hyperframes render .`; wrong cwd when using a relative path; a CI checkout step that did not clone the project; a path with a trailing slash or space that resolved wrong; a deleted/moved project folder.","solutions":["Verify the path exists and is a directory: `ls -ld <path>`.","Pass the project directory (containing index.html), not the HTML file itself.","Use an absolute path or run from inside the project with '.'.","Check for typos, trailing spaces, or unexpanded ~ (use $HOME or the expanded path)."],"exampleFix":"# before: passed the html file, not the directory\nhyperframes render ./index.html\n# after\nhyperframes render .","handlingStrategy":"validation","validationCode":"import { existsSync, statSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nfunction ensureProjectDir(dirArg: string | undefined): string {\n  const dir = resolve(dirArg ?? '.');\n  if (!existsSync(dir) || !statSync(dir).isDirectory()) {\n    throw new Error(`Not a directory: ${dir}`);\n  }\n  return dir;\n}","typeGuard":"import { Stats } from 'node:fs';\nfunction isDirectory(stats: Stats): boolean {\n  return stats.isDirectory();\n}","tryCatchPattern":"try {\n  return resolveProjectOrThrow(dirArg);\n} catch (err) {\n  if (err instanceof InvalidProjectError && /^Not a directory:/.test(err.message)) {\n    console.error(err.message, '— pass the project directory, not a file.');\n  } else throw err;\n}","preventionTips":["Pass the project directory (the folder containing index.html), not the HTML file.","Use absolute paths in CI to avoid cwd-relative surprises.","Verify the path with ls -ld before invoking the CLI."],"tags":["cli","project","filesystem","validation","argument"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}