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

  1. Check the path exists with fs.existsSync/path.resolve before calling and fix it
  2. Use absolute paths (path.resolve(__dirname, ...)) instead of relative ones
  3. Verify the pipeline step that produces the video file actually succeeded
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/967fe0d48fa078cd. Report an issue: GitHub.