{"record":{"id":"133d59746e8c7563","repo":"jackwener/OpenCLI","slug":"video-file-is-empty-filepath","errorCode":null,"errorMessage":"Video file is empty: ${filePath}","messagePattern":"Video file is empty: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/_shared/tos-upload.js","lineNumber":273,"sourceCode":"        throw new CommandExecutionError(`TOS complete multipart upload failed with status ${res.status}: ${res.body}`, 'Check that all parts were uploaded successfully.');\n    }\n    return parsed?.data?.key || null;\n}\nlet _readSyncOverride = null;\n/** @internal — for testing only */\nexport function setReadSyncOverride(fn) {\n    _readSyncOverride = fn;\n}\n// ── Public API ───────────────────────────────────────────────────────────────\nexport async function tosUpload(options) {\n    const { filePath, uploadInfo, credentials, onProgress } = options;\n    // Validate file exists\n    if (!fs.existsSync(filePath)) {\n        throw new CommandExecutionError(`Video file not found: ${filePath}`, 'Ensure the file path is correct and accessible.');\n    }\n    const { size: fileSize } = fs.statSync(filePath);\n    if (fileSize === 0) {\n        throw new CommandExecutionError(`Video file is empty: ${filePath}`);\n    }\n    const { tos_upload_url: tosUrl, auth, upload_header: uploadHeader, user_id: userId } = uploadInfo;\n    const parsedTosUrl = new URL(tosUrl);\n    const region = extractRegionFromHost(parsedTosUrl.host);\n    const resumePath = getResumeFilePath(filePath);\n    let resumeState = loadResumeState(resumePath, fileSize);\n    let uploadId;\n    let completedParts;\n    if (resumeState) {\n        // Resume from previous state\n        uploadId = resumeState.uploadId;\n        completedParts = resumeState.parts;\n    }\n    else {\n        // Start fresh\n        uploadId = await initMultipartUpload(tosUrl, auth, uploadHeader, userId);\n        completedParts = [];\n        saveResumeState(resumePath, { uploadId, fileSize, parts: completedParts });","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/tos-upload.js#L255-L291","documentation":"tosUpload rejects empty files early: after confirming existence, if fs.statSync(filePath).size === 0 it throws this CommandExecutionError. TOS multipart upload of zero bytes is invalid, so it fails fast.","triggerScenarios":"Calling tosUpload on a file that exists but is 0 bytes — interrupted encoder output, truncated download, or a file created as a placeholder but never written.","commonSituations":"Previous render/encode step crashed after touch()ing the output; disk-full left a zero-length file; piping output that produced nothing.","solutions":["Regenerate the video file; verify with fs.statSync(p).size > 0 before uploading","Fix the upstream encode/render step that produced an empty file","Check disk space and write errors from the producing step","Add an explicit size precheck with a clear message in your pipeline"],"exampleFix":"// before\nawait tosUpload({ filePath, ... });\n// after\nconst { size } = fs.statSync(filePath);\nif (size === 0) { /* regenerate or abort */ }\nawait tosUpload({ filePath, ... });","handlingStrategy":"validation","validationCode":"const { size } = fs.statSync(filePath);\nif (size === 0) throw new Error(`refusing to upload empty file: ${filePath}`);","typeGuard":"function isNonEmptyFile(p) {\n  try { return fs.statSync(p).size > 0; } catch { return false; }\n}","tryCatchPattern":"try { await tosUpload(options); }\ncatch (e) {\n  if (String(e.message).startsWith('Video file is empty')) {\n    await regenerateVideo(options.filePath);\n    return tosUpload(options);\n  }\n  throw e;\n}","preventionTips":["Verify encoder output size > 0 before handing off to upload","Watch for zero-byte files caused by disk-full or crashed writers","Delete or quarantine stale placeholder files","Add pipeline assertions that outputs are non-empty"],"tags":["filesystem","validation","empty-file"],"backgroundTag":"empty-file-upload","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}