heygen-com/hyperframes · critical
Project archive must include index.html at the root. Check t
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.
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)
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 (source=${source}): HYP
- [chromium] Chrome binary unavailable (source=${source}): HYP
- [s3Transport] upload source missing: ${localPath}
- [s3Transport] tar source must be an existing directory: ${so
- [s3Transport] tarball missing: ${tarballPath}
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/be898f6064962bd0.
Report an issue: GitHub.