heygen-com/hyperframes · critical
Project archive must include index.html at the root. Check…
Error message
Project archive must include index.html at the root. Check that .hyperframesignore does not exclude it.
What it means
buildPublishFileMap walks the project dir (respecting .hyperframesignore, IGNORED_DIRS like node_modules/.git/dist, and DEFAULT_PROJECT_IGNORE like /renders/ /snapshots/) and collects relative file paths. If 'index.html' is not among the collected relative paths, publish cannot proceed — a published project must have an entry composition. The message points at .hyperframesignore because that is the usual culprit: an overly broad ignore pattern excluded index.html.
Solutions
- Confirm index.html exists at the ROOT of the directory passed to publish: ls <project-dir>/index.html.
- Inspect .hyperframesignore for patterns matching index.html (e.g. `*.html`, `/index.*`) and remove/narrow them.
- Run publish from the directory that actually contains index.html.
- If index.html is generated, ensure the generation step runs before publish.
Example fix
# .hyperframesignore before (excludes index.html) *.html # after /renders/*.html /snapshots/*.html
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import ignore from 'ignore';
function ensureIndexHtmlIncluded(projectDir: string): void {
const abs = resolve(projectDir, 'index.html');
if (!existsSync(abs)) throw new Error('index.html missing from project root');
const ig = ignore().add(readFileSync(resolve(projectDir, '.hyperframesignore'), 'utf-8').catch?.() ?? '');
if (ig.ignores('index.html')) throw new Error('.hyperframesignore excludes index.html');
} Try / catch
try {
return buildPublishFileMap(projectDir);
} catch (err) {
if (err instanceof Error && /must include index.html at the root/.test(err.message)) {
// surface the .hyperframesignore contents so the user can find the offending pattern
console.error(err.message, '\nCheck .hyperframesignore patterns.');
} else throw err;
} Prevention
- Never put a bare `*.html` in .hyperframesignore — scope excludes to subfolders like /renders/.
- Confirm `ls <project>/index.html` succeeds before publishing.
- Run `npx hyperframes lint` before publish — it flags a missing entry file early.
When it happens
Trigger: index.html is missing from the project root entirely; .hyperframesignore contains a pattern that matches index.html (e.g. `/*.html`, `/index.*`, `index.html`); index.html exists only in a subdirectory (the walker records relative paths, so a nested index.html becomes 'subdir/index.html', not 'index.html'); the project root passed to publish is the wrong directory.
Common situations: User added `*.html` or `/index.html` to .hyperframesignore to exclude build artifacts, accidentally excluding the entry; a monorepo where the publish root was set to the workspace, not the package; an index.html that lives in src/ but publish is run from the parent; a generated project where index.html was gitignored and not checked out.
Related errors
- [chromium] Chrome binary unavailable
- ambiguous motion sidecars in
- Audio FX input is missing
- [BrowserManager] Chrome binary not found at…
- [BrowserManager] Chrome binary not found at…
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/be898f6064962bd0.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/utils/publishProject.ts:491
}
}
return ctx.externalMap.size;
}
/**
* Walk the project dir, read every non-ignored file, and localize external
* (out-of-project) asset references. Returns the in-memory archive file map —
* the seam `publish.ts` hooks a proxy-baking transform into (U6) between this
* and `zipPublishFileMap` below. `cloud render` never sees this seam: it
* keeps calling `createPublishArchive` directly.
*/
export function buildPublishFileMap(projectDir: string): Map<string, Buffer> {
const absProjectDir = resolve(projectDir);
const filePaths: string[] = [];
collectProjectFiles(absProjectDir, absProjectDir, filePaths, createProjectIgnore(absProjectDir));
if (!filePaths.includes("index.html")) {
throw new Error(
"Project archive must include index.html at the root. Check that .hyperframesignore does not exclude it.",
);
}
const fileContents = new Map<string, Buffer>();
for (const filePath of filePaths) {
fileContents.set(filePath, readFileSync(join(absProjectDir, filePath)));
}
localizeExternalAssets(absProjectDir, fileContents);
return fileContents;
}
/** Zip an in-memory archive file map (from `buildPublishFileMap`, optionally
* transformed in between, e.g. by proxy baking) into the final archive buffer. */
export function zipPublishFileMap(fileContents: Map<string, Buffer>): PublishArchiveResult {
const archive = new AdmZip();
for (const [filePath, content] of fileContents) {View on GitHub (pinned to c2996c8626)