heygen-com/hyperframes · error
[s3Transport] tarball missing: ${tarballPath}
Error message
[s3Transport] tarball missing: ${tarballPath} What it means
Thrown by untarDirectory when the tarballPath passed to the extract step does not exist on disk. untarDirectory is the unpack step the Lambda handler uses to materialize a downloaded plan tarball into a planDir before rendering. The check precedes the rmSync/mkdirSync of destDir so a missing source does not wipe a valid existing destination. This typically indicates the preceding download step (downloadS3ObjectToFile) failed or wrote to a different path.
Source
Thrown at packages/aws-lambda/src/s3Transport.ts:286
* userland tools and does NOT include `tar` in `/usr/bin`.
*/
export async function tarDirectory(sourceDir: string, destTarball: string): Promise<void> {
if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) {
throw new Error(`[s3Transport] tar source must be an existing directory: ${sourceDir}`);
}
mkdirSync(dirname(destTarball), { recursive: true });
await tar.create({ gzip: true, file: destTarball, cwd: sourceDir }, ["."]);
}
/**
* Extract a `.tar.gz` produced by {@link tarDirectory} into `destDir`.
* The directory is created (or cleared) before extraction so a retried
* invocation doesn't observe stale files from a prior run on the same
* warm Lambda container.
*/
export async function untarDirectory(tarballPath: string, destDir: string): Promise<void> {
if (!existsSync(tarballPath)) {
throw new Error(`[s3Transport] tarball missing: ${tarballPath}`);
}
// Wipe target so the warm container's prior planDir doesn't bleed into
// the new invocation. Lambda re-uses /tmp across invocations on the same
// container.
if (existsSync(destDir)) {
rmSync(destDir, { recursive: true, force: true });
}
mkdirSync(destDir, { recursive: true });
await tar.extract({ file: tarballPath, cwd: destDir });
}
View on GitHub (pinned to c2996c8626)
Solutions
- Ensure the same path constant is used for both downloadS3ObjectToFile and untarDirectory — derive both from one variable.
- Check that downloadS3ObjectToFile resolved without throwing before calling untarDirectory.
- Verify Lambda /tmp still contains the file (existsSync) immediately before the extract call.
- If the download is retried, confirm the retry wrote to the same path.
Example fix
// before
await downloadS3ObjectToFile(client, uri, '/tmp/plan.tar.gz');
await untarDirectory('/tmp/plan.tgz', destDir); // mismatched name
// after
const tarball = path.join(os.tmpdir(), 'plan.tar.gz');
await downloadS3ObjectToFile(client, uri, tarball);
await untarDirectory(tarball, destDir); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'node:fs';
function assertTarballExists(tarballPath: string): void {
if (!existsSync(tarballPath)) {
throw new Error(`download did not produce tarball: ${tarballPath}`);
}
} Type guard
import { statSync } from 'node:fs';
const isExistingFile = (p: string): boolean => {
try { return statSync(p).isFile(); } catch { return false; }
}; Prevention
- Use a single path variable for both download and extract.
- Confirm downloadS3ObjectToFile resolved without throwing before extracting.
- On warm Lambda containers, check /tmp for the file right before extract.
When it happens
Trigger: The Lambda handler downloads a plan tarball to /tmp/X.tar.gz then calls untarDirectory with a path that differs (typo, wrong prefix, wrong extension), or the download threw and was swallowed. Also fires when a warm container's /tmp was cleared between download and extract.
Common situations: Download path and extract path constructed from different template variables; a GetObject error was caught but not re-thrown; Lambda /tmp eviction between warm-invocation steps; the tarball key in the manifest doesn't match the local naming convention.
Related errors
- [s3Transport] tar source must be an existing directory: ${so
- [s3Transport] upload source missing: ${localPath}
- [deploySite] projectDir is not a directory: ${opts.projectDi
- [getRenderProgress] executionArn is required
- [renderToLambda] bucketName is required
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/34907024348ddb1e.
Report an issue: GitHub.