{"record":{"id":"0cce597377835091","repo":"opendatalab/MinerU","slug":"input-path-must-be-a-file-or-directory-path","errorCode":null,"errorMessage":"Input path must be a file or directory: {path}","messagePattern":"Input path must be a file or directory: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"demo/demo.py","lineNumber":28,"sourceCode":"from mineru.cli.common import image_suffixes, office_suffixes, pdf_suffixes\nfrom mineru.utils.guess_suffix_or_lang import guess_suffix_by_path\n\nSUPPORTED_INPUT_SUFFIXES = set(pdf_suffixes + image_suffixes + office_suffixes)\n\n\ndef collect_input_files(input_path: str | Path) -> list[Path]:\n    path = Path(input_path).expanduser().resolve()\n    if not path.exists():\n        raise FileNotFoundError(f\"Input path does not exist: {path}\")\n\n    if path.is_file():\n        file_suffix = guess_suffix_by_path(path)\n        if file_suffix not in SUPPORTED_INPUT_SUFFIXES:\n            raise ValueError(f\"Unsupported input file type: {path.name}\")\n        return [path]\n\n    if not path.is_dir():\n        raise ValueError(f\"Input path must be a file or directory: {path}\")\n\n    input_files = sorted(\n        (\n            candidate.resolve()\n            for candidate in path.iterdir()\n            if candidate.is_file()\n            and guess_suffix_by_path(candidate) in SUPPORTED_INPUT_SUFFIXES\n        ),\n        key=lambda item: item.name,\n    )\n    if not input_files:\n        raise ValueError(f\"No supported files found in directory: {path}\")\n    return input_files\n\n\ndef build_form_data(\n    language: str,\n    backend: str,","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/opendatalab/MinerU/blob/4fe4bde114a23ee5dd637eae99b767f4669bf58c/demo/demo.py#L10-L46","documentation":"Raised by collect_input_files() when the path exists and is neither a regular file nor a directory — i.e. it is a special filesystem node such as a FIFO, socket, device, or a broken symlink that resolve() still passes exists() for in some configurations. The function only accepts regular files and directories.","triggerScenarios":"Passing /dev/stdin, a named pipe, a Unix socket path, or another non-regular file as input_path.","commonSituations":"Piping data via process substitution (e.g. <(curl ...)) which creates a FIFO; pointing at device nodes; exotic filesystems that report odd file types.","solutions":["Write the streamed data to a real temporary file first, then pass that file's path.","If you intended a directory or file, check for a typo or a symlink resolving to a special node."],"exampleFix":"# before\nfiles = collect_input_files(\"/dev/stdin\")\n\n# after\nimport tempfile, sys\nwith tempfile.NamedTemporaryFile(suffix=\".pdf\", delete=False) as f:\n    f.write(sys.stdin.buffer.read())\nfiles = collect_input_files(f.name)","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef is_regular_file_or_dir(value: str) -> bool:\n    p = Path(value).expanduser().resolve()\n    return p.is_file() or p.is_dir()","typeGuard":null,"tryCatchPattern":"try:\n    files = collect_input_files(path)\nexcept ValueError as e:\n    if \"must be a file or directory\" in str(e):\n        materialize_to_temp_file(path)  # e.g. read FIFO -> tmp .pdf, retry\n    else:\n        raise","preventionTips":["Never pass /dev/stdin, named pipes, or process substitution directly.","Materialize streams into a NamedTemporaryFile before parsing.","Check Path.is_file()/is_dir() in your own preflight."],"tags":["filesystem","input-validation","path"],"backgroundTag":null,"analyzedSha":"4fe4bde114a23ee5dd637eae99b767f4669bf58c","analyzedAt":"2026-08-14T21:29:18.456Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}