{"record":{"id":"34907024348ddb1e","repo":"heygen-com/hyperframes","slug":"s3transport-tarball-missing-tarballpath","errorCode":null,"errorMessage":"[s3Transport] tarball missing: ${tarballPath}","messagePattern":"\\[s3Transport\\] tarball missing: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/aws-lambda/src/s3Transport.ts","lineNumber":286,"sourceCode":" * userland tools and does NOT include `tar` in `/usr/bin`.\n */\nexport async function tarDirectory(sourceDir: string, destTarball: string): Promise<void> {\n  if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) {\n    throw new Error(`[s3Transport] tar source must be an existing directory: ${sourceDir}`);\n  }\n  mkdirSync(dirname(destTarball), { recursive: true });\n  await tar.create({ gzip: true, file: destTarball, cwd: sourceDir }, [\".\"]);\n}\n\n/**\n * Extract a `.tar.gz` produced by {@link tarDirectory} into `destDir`.\n * The directory is created (or cleared) before extraction so a retried\n * invocation doesn't observe stale files from a prior run on the same\n * warm Lambda container.\n */\nexport async function untarDirectory(tarballPath: string, destDir: string): Promise<void> {\n  if (!existsSync(tarballPath)) {\n    throw new Error(`[s3Transport] tarball missing: ${tarballPath}`);\n  }\n  // Wipe target so the warm container's prior planDir doesn't bleed into\n  // the new invocation. Lambda re-uses /tmp across invocations on the same\n  // container.\n  if (existsSync(destDir)) {\n    rmSync(destDir, { recursive: true, force: true });\n  }\n  mkdirSync(destDir, { recursive: true });\n  await tar.extract({ file: tarballPath, cwd: destDir });\n}\n","sourceCodeStart":268,"sourceCodeEnd":297,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/aws-lambda/src/s3Transport.ts#L268-L297","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait downloadS3ObjectToFile(client, uri, '/tmp/plan.tar.gz');\nawait untarDirectory('/tmp/plan.tgz', destDir); // mismatched name\n\n// after\nconst tarball = path.join(os.tmpdir(), 'plan.tar.gz');\nawait downloadS3ObjectToFile(client, uri, tarball);\nawait untarDirectory(tarball, destDir);","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nfunction assertTarballExists(tarballPath: string): void {\n  if (!existsSync(tarballPath)) {\n    throw new Error(`download did not produce tarball: ${tarballPath}`);\n  }\n}","typeGuard":"import { statSync } from 'node:fs';\nconst isExistingFile = (p: string): boolean => {\n  try { return statSync(p).isFile(); } catch { return false; }\n};","tryCatchPattern":null,"preventionTips":["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."],"tags":["tar","filesystem","validation","plan","aws-lambda"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}