heygen-com/hyperframes · error · Error
[handler] chunk URI at index ${i} is empty
Error message
[handler] chunk URI at index ${i} is empty What it means
Thrown by `downloadChunks` during the `assemble` action when a chunk URI in the input array is empty (falsy). Each chunk URI must resolve to an S3 object; an empty entry usually means the planner emitted a sparse array or a chunk index was skipped.
Source
Thrown at packages/aws-lambda/src/handler.ts:752
async function downloadChunkObjects(
s3: S3Client,
uris: string[],
workDir: string,
format: DistributedFormat,
): Promise<string[]> {
const chunksDir = join(workDir, "chunks");
mkdirSync(chunksDir, { recursive: true });
// Each chunk is an independent S3 GET (+ untar for png-sequence). Run
// them in parallel — assemble's wall-clock is otherwise dominated by
// `Σ chunk-download-ms` instead of `max(chunk-download-ms)`. Preserve
// the input order by writing into a pre-sized array rather than
// pushing as each task settles.
const local: string[] = new Array<string>(uris.length);
await Promise.all(
uris.map(async (uri, i) => {
if (!uri) {
throw new Error(`[handler] chunk URI at index ${i} is empty`);
}
const { key } = parseS3Uri(uri);
const localPath = join(chunksDir, basename(key));
await downloadS3ObjectToFile(s3, uri, localPath);
if (format === "png-sequence") {
const dirPath = join(chunksDir, `frames-${pad(i)}`);
await untarDirectory(localPath, dirPath);
local[i] = dirPath;
} else {
local[i] = localPath;
}
}),
);
return local;
}
// ── Helpers ─────────────────────────────────────────────────────────────────
View on GitHub (pinned to c2996c8626)
Solutions
- Inspect the assemble event's chunk URI array in CloudWatch to locate the gap.
- Ensure the planner emits a contiguous, fully-populated URI array (no skipped indices).
- Re-run `plan` to regenerate a complete chunk list before `assemble`.
- If a chunk legitimately has no output, define the protocol for that slot rather than leaving it empty.
Example fix
// before: sparse chunk list const uris = ["s3://b/chunk-0", "", "s3://b/chunk-2"]; // after: contiguous, fully populated const uris = ["s3://b/chunk-0", "s3://b/chunk-1", "s3://b/chunk-2"];
Defensive patterns
Strategy: validation
Validate before calling
function assertChunkUris(uris: unknown[]): void {
uris.forEach((uri, i) => {
if (typeof uri !== "string" || uri.length === 0) {
throw new Error(`chunk URI at index ${i} is empty`);
}
});
}
// call before downloadChunks Type guard
function isNonEmptyStringArray(value: unknown): value is string[] {
return Array.isArray(value) && value.every((v) => typeof v === "string" && v.length > 0);
} Prevention
- Build the chunk URI array with a contiguous `for` loop keyed by index so no slots are skipped.
- After plan, assert the chunk list is dense before persisting it.
- Log the chunk-URI array length and indices in CloudWatch for assemble events.
When it happens
Trigger: `downloadChunks(uris, ...)` with an element that is `""`, `null`, or `undefined` at index `i` — i.e. the assemble event's chunk-URI list is sparse or has a gap.
Common situations: Planner bug that built a sparse chunk list when a chunk produced no output; renderChunk result aggregation that left a hole at a failed/empty chunk index; JSON round-trip that dropped an undefined element.
Related errors
- [handler] unknown Action: ${JSON.stringify((_exhaustive as {
- [handler] event has no recognised Action; unwrapped ${MAX_EN
- BeginFrame probe timeout before ${label}
- [chromium] Chrome binary unavailable (source=${source}): @sp
- [chromium] Chrome binary unavailable (source=${source}): HYP
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/bf3bf55545d6749b.
Report an issue: GitHub.