hiyouga/LlamaFactory · error · HTTPException

Local file access is disabled.

Error message

Local file access is disabled.

What it means

Raised as HTTP 403 by check_lfi_path when a request references a local file path (image/video/audio) but the ALLOW_LOCAL_FILES flag is false. It is a deliberate local-file-inclusion (LFI) protection: the API refuses to read any local media unless local files were explicitly enabled at server startup.

Source

Thrown at src/llamafactory/api/common.py:55

def dictify(data: "BaseModel") -> dict[str, Any]:
    try:  # pydantic v2
        return data.model_dump(exclude_unset=True)
    except AttributeError:  # pydantic v1
        return data.dict(exclude_unset=True)


def jsonify(data: "BaseModel") -> str:
    try:  # pydantic v2
        return json.dumps(data.model_dump(exclude_unset=True), ensure_ascii=False)
    except AttributeError:  # pydantic v1
        return data.json(exclude_unset=True, ensure_ascii=False)


def check_lfi_path(path: str) -> None:
    """Checks if a given path is vulnerable to LFI. Raises HTTPException if unsafe."""
    if not ALLOW_LOCAL_FILES:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Local file access is disabled.")

    try:
        os.makedirs(SAFE_MEDIA_PATH, exist_ok=True)
        real_path = os.path.realpath(path)
        safe_path = os.path.realpath(SAFE_MEDIA_PATH)

        if not real_path.startswith(safe_path):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN, detail="File access is restricted to the safe media directory."
            )
    except Exception:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid or inaccessible file path.")


def check_ssrf_url(url: str) -> None:
    """Checks if a given URL is vulnerable to SSRF. Raises HTTPException if unsafe."""
    try:
        parsed_url = urlparse(url)

View on GitHub (pinned to f28afaf635)

Solutions

  1. Start the API with local file access enabled (set ALLOW_LOCAL_FILES=true or the corresponding launch flag/env in this deployment).
  2. Alternatively serve the media over HTTP(S) so the SSRF-checked URL path is used instead.
  3. Alternatively base64-encode small media into data: URLs, which bypass the local-path branch.
  4. If enabling local files, also place media under SAFE_MEDIA_PATH since access is sandboxed to it.

Example fix

# before
llamafactory-cli api ...  # default: local files disabled
# after
ALLOW_LOCAL_FILES=true llamafactory-cli api ...
Defensive patterns

Strategy: validation

Validate before calling

def is_local_path(u):
    return not u.startswith(("http://", "https://", "data:"))

for url in media_urls:
    if is_local_path(url):
        assert os.environ.get("ALLOW_LOCAL_FILES") == "true", "encode as data URL or use https"

Type guard

const isLocalPath = (u) => !/^(https?:|data:)/.test(u);

Try / catch

catch (e) { if (e.status === 403 && e.detail === 'Local file access is disabled.') { return fetchDataUrl(path); /* or https URL */ } throw e; }

Prevention

When it happens

Trigger: Sending image_url/video_url/audio_url whose value is a local filesystem path (e.g. /home/user/img.png) while the server was started without the flag/env that sets ALLOW_LOCAL_FILES=true.

Common situations: Pointing the API at a local dataset directory for convenience in development; migrating from an older LlamaFactory version where local paths were unrestricted; forgetting the deployment hardening added for LFI.

Related errors


AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14). Data as JSON: /api/errors/c12f38ce4c5ff02a. Report an issue: GitHub.