ytdl-org/youtube-dl · error · PostProcessingError

Command returned error code %d

Error message

Command returned error code %d

What it means

Raised by ExecAfterDownloadPP (--exec CMD) when the executed shell command exits with a non-zero status. The message includes the actual exit code. The command runs through the shell with the filepath substituted for '{}', so any failure inside the user-supplied command surfaces here.

Source

Thrown at youtube_dl/postprocessor/execafterdownload.py:28

)


class ExecAfterDownloadPP(PostProcessor):
    def __init__(self, downloader, exec_cmd):
        super(ExecAfterDownloadPP, self).__init__(downloader)
        self.exec_cmd = exec_cmd

    def run(self, information):
        cmd = self.exec_cmd
        if '{}' not in cmd:
            cmd += ' {}'

        cmd = cmd.replace('{}', compat_shlex_quote(information['filepath']))

        self._downloader.to_screen('[exec] Executing command: %s' % cmd)
        retCode = subprocess.call(encodeArgument(cmd), shell=True)
        if retCode != 0:
            raise PostProcessingError(
                'Command returned error code %d' % retCode)

        return [], information

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Run the printed command manually ('[exec] Executing command: ...' line) with the same file to see the real failure
  2. Fix quoting: keep '{} ' inside quotes if paths contain spaces, e.g. --exec 'mv "{}" /dst/'
  3. Make the command exit 0 on success — append '|| true' only if failure is genuinely acceptable
  4. Ensure the command exists on PATH in the environment youtube-dl runs in

Example fix

# before
youtube-dl --exec 'ffmpeg -i {} out.mp4' URL
# after (quoted target, explicit exit handling)
youtube-dl --exec 'ffmpeg -i "{}" "{}.mp4" && echo done' URL
Defensive patterns

Strategy: try-catch

Validate before calling

import shutil

def exec_hook_runnable(cmd):
    base = cmd.split()[0]
    return shutil.which(base) is not None

assert exec_hook_runnable(opts['exec_cmd']), 'exec hook binary not on PATH'

Try / catch

try:
    ydl.download([url])
except PostProcessingError as e:
    if 'Command returned error code' in str(e):
        log.warning('post-download hook failed for %s (check --exec command)', information_path)

Prevention

When it happens

Trigger: Passing --exec 'rm {} && notify-send done' where a step fails (nonexistent file, permission denied, typo'd command); commands that assume a different cwd; commands whose last statement returns non-zero (e.g. grep with no match).

Common situations: Hooking --exec into scripts to move files, call ffmpeg again, or fire desktop notifications; quoting mistakes so '{}' splits into multiple shell words; commands valid in zsh but not sh.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/b5cb4bb84a208bee. Report an issue: GitHub.