HKUDS/DeepTutor · error · MinerUError

Configured MinerU CLI path is not an executable file

Error message

Configured MinerU CLI path is not an executable file: {probe['path']}. Fix it in Settings → MinerU (or clear it to auto-detect from PATH).

What it means

local_cli_probe reported that the explicitly configured MinerU CLI path (Settings → MinerU) is not an executable file. The user pinned a path that is missing, wrong, or lacks the executable bit; the message tells them to fix it or clear it to fall back to PATH auto-detection.

Solutions

  1. Fix or clear local_cli_path in Settings → MinerU so auto-detection from PATH takes over.
  2. Verify with: ls -l /path/to/mineru && /path/to/mineru --version.
  3. If correct, chmod +x the CLI.
  4. Confirm the venv where mineru is installed is the one the app runs in.

Example fix

# before
config.local_cli_path = "/usr/local/bin/mineru"  # stale

# after
config.local_cli_path = ""  # auto-detect from PATH
Defensive patterns

Strategy: validation

Validate before calling

import os, stat

def cli_ok(path: str) -> bool:
    if not (path or "").strip():
        return True  # auto-detect
    st = os.stat(path)
    return stat.S_ISREG(st.st_mode) and bool(st.st_mode & 0o111)

Try / catch

try:
    parse_pdf_to_workdir(...)
except MinerUError as e:
    if "not an executable" in str(e):
        fix_cli_setting()

Prevention

When it happens

Trigger: config.local_cli_path is a non-empty string that local_cli_probe() cannot resolve to an executable file — wrong path, missing file, or no execute permission.

Common situations: Typo in the path, path from another machine/container, CLI uninstalled, or a non-executable script (chmod -x).

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/2c82e77c0f54684b. Report an issue: GitHub.

Appendix: source

Thrown at deeptutor/services/parsing/engines/mineru/backend.py:133


def _parse_local(
    pdf_path: Path,
    output_base: Path,
    *,
    config: MinerUConfig,
    on_output: Callable[[str], None] | None = None,
) -> Path:
    """Local-CLI branch: delegate to the existing subprocess parser and return
    the deterministic output directory it writes to (``<base>/<stem>``)."""
    from .local import parse_pdf_with_mineru
    from .models import model_env_overrides, render_env_overrides

    cli_command = None
    if (config.local_cli_path or "").strip():
        probe = local_cli_probe(config.local_cli_path)
        if not probe["found"]:
            raise MinerUError(
                f"Configured MinerU CLI path is not an executable file: {probe['path']}. "
                "Fix it in Settings → MinerU (or clear it to auto-detect from PATH)."
            )
        cli_command = probe["path"]

    # A lazy first-parse model download must honor the configured source and
    # custom address, not just the explicit Download button.
    download_env = model_env_overrides(config.model_download_source, config.model_download_endpoint)
    # Only the local CLI renders pages in this process tree; cloud mode never
    # does, so the Windows render-thread guard belongs on this branch alone.
    subprocess_env = {**download_env, **render_env_overrides()}

    logger.info("Parsing %s via local MinerU CLI (%s)", pdf_path.name, cli_command or "PATH")
    ok = parse_pdf_with_mineru(
        str(pdf_path),
        str(output_base),
        on_output=on_output,
        cli_command=cli_command,

View on GitHub (pinned to 3e82f13042)