{"record":{"id":"b5cb4bb84a208bee","repo":"ytdl-org/youtube-dl","slug":"command-returned-error-code-d","errorCode":null,"errorMessage":"Command returned error code %d","messagePattern":"Command returned error code (.+?)","errorType":"exception","errorClass":"PostProcessingError","httpStatus":null,"severity":"error","filePath":"youtube_dl/postprocessor/execafterdownload.py","lineNumber":28,"sourceCode":")\n\n\nclass ExecAfterDownloadPP(PostProcessor):\n    def __init__(self, downloader, exec_cmd):\n        super(ExecAfterDownloadPP, self).__init__(downloader)\n        self.exec_cmd = exec_cmd\n\n    def run(self, information):\n        cmd = self.exec_cmd\n        if '{}' not in cmd:\n            cmd += ' {}'\n\n        cmd = cmd.replace('{}', compat_shlex_quote(information['filepath']))\n\n        self._downloader.to_screen('[exec] Executing command: %s' % cmd)\n        retCode = subprocess.call(encodeArgument(cmd), shell=True)\n        if retCode != 0:\n            raise PostProcessingError(\n                'Command returned error code %d' % retCode)\n\n        return [], information\n","sourceCodeStart":10,"sourceCodeEnd":32,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/postprocessor/execafterdownload.py#L10-L32","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Run the printed command manually ('[exec] Executing command: ...' line) with the same file to see the real failure","Fix quoting: keep '{} ' inside quotes if paths contain spaces, e.g. --exec 'mv \"{}\" /dst/'","Make the command exit 0 on success — append '|| true' only if failure is genuinely acceptable","Ensure the command exists on PATH in the environment youtube-dl runs in"],"exampleFix":"# before\nyoutube-dl --exec 'ffmpeg -i {} out.mp4' URL\n# after (quoted target, explicit exit handling)\nyoutube-dl --exec 'ffmpeg -i \"{}\" \"{}.mp4\" && echo done' URL","handlingStrategy":"try-catch","validationCode":"import shutil\n\ndef exec_hook_runnable(cmd):\n    base = cmd.split()[0]\n    return shutil.which(base) is not None\n\nassert exec_hook_runnable(opts['exec_cmd']), 'exec hook binary not on PATH'","typeGuard":null,"tryCatchPattern":"try:\n    ydl.download([url])\nexcept PostProcessingError as e:\n    if 'Command returned error code' in str(e):\n        log.warning('post-download hook failed for %s (check --exec command)', information_path)","preventionTips":["Test the --exec command manually with a sample path before batch use","Quote '{}' inside the hook so paths with spaces stay one shell word","Remember the file IS downloaded — a failing hook need not discard the result"],"tags":["exec","shell","hook","postprocessor"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}