jackwener/OpenCLI · error · CommandExecutionError
Video file not found: ${filePath}
Error message
Video file not found: ${filePath} What it means
tosUpload validates that the video file exists before reading it; this CommandExecutionError is thrown when fs.existsSync(filePath) is false. Nothing is uploaded.
Source
Thrown at clis/douyin/_shared/tos-upload.js:269
catch {
parsed = null;
}
if (res.status !== 200 || parsed?.code !== 2000) {
throw new CommandExecutionError(`TOS complete multipart upload failed with status ${res.status}: ${res.body}`, 'Check that all parts were uploaded successfully.');
}
return parsed?.data?.key || null;
}
let _readSyncOverride = null;
/** @internal — for testing only */
export function setReadSyncOverride(fn) {
_readSyncOverride = fn;
}
// ── Public API ───────────────────────────────────────────────────────────────
export async function tosUpload(options) {
const { filePath, uploadInfo, credentials, onProgress } = options;
// Validate file exists
if (!fs.existsSync(filePath)) {
throw new CommandExecutionError(`Video file not found: ${filePath}`, 'Ensure the file path is correct and accessible.');
}
const { size: fileSize } = fs.statSync(filePath);
if (fileSize === 0) {
throw new CommandExecutionError(`Video file is empty: ${filePath}`);
}
const { tos_upload_url: tosUrl, auth, upload_header: uploadHeader, user_id: userId } = uploadInfo;
const parsedTosUrl = new URL(tosUrl);
const region = extractRegionFromHost(parsedTosUrl.host);
const resumePath = getResumeFilePath(filePath);
let resumeState = loadResumeState(resumePath, fileSize);
let uploadId;
let completedParts;
if (resumeState) {
// Resume from previous state
uploadId = resumeState.uploadId;
completedParts = resumeState.parts;
}
else {View on GitHub (pinned to 49907e53dc)
Solutions
- Check the path exists with fs.existsSync/path.resolve before calling and fix it
- Use absolute paths (path.resolve(__dirname, ...)) instead of relative ones
- Verify the pipeline step that produces the video file actually succeeded
- Check file permissions and that the path separator matches the OS
Example fix
// before
await tosUpload({ filePath: 'out/video.mp4', ... });
// after
const filePath = path.resolve('out/video.mp4');
if (!fs.existsSync(filePath)) throw new Error(`missing input: ${filePath}`);
await tosUpload({ filePath, ... }); Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
const abs = path.resolve(filePath);
if (!fs.existsSync(abs) || !fs.statSync(abs).isFile()) {
throw new Error(`video file missing: ${abs}`);
} Type guard
function isExistingFile(p) {
try { return fs.statSync(p).isFile(); } catch { return false; }
} Try / catch
try { await tosUpload(options); }
catch (e) {
if (String(e.message).startsWith('Video file not found')) {
console.error(`check path: ${options.filePath} (cwd=${process.cwd()})`);
}
throw e;
} Prevention
- Always pass absolute paths to tosUpload
- Assert the producing pipeline step wrote the file before uploading
- Log process.cwd() when debugging relative-path issues
- Add a preflight existsSync check with a clear error message
When it happens
Trigger: Calling tosUpload with a filePath that doesn't exist — typo'd path, relative path resolved from a different cwd, deleted temp file, or wrong path separator.
Common situations: Script run from a different working directory than expected; output file from a prior render step missing because that step failed; Windows-style path used on POSIX.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search query must not be empty
- arxiv author cannot be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/967fe0d48fa078cd.
Report an issue: GitHub.