mudler/LocalAI · error · ValueError

Dataset source path is outside the allowed directory

Error message

Dataset source path is outside the allowed directory

What it means

The TRL fine-tuning backend restricts local dataset files to an allowed directory (LOCALAI_DATASET_DIR env var, default: the backend's cwd). When request.dataset_source is an existing local path, its realpath must equal or live under the allowed dir; symlinked or ../-escaping paths are rejected via the os.sep suffix check, preventing path traversal.

Source

Thrown at backend/python/trl/backend.py:315

                lora_alpha=lora_alpha,
                lora_dropout=lora_dropout,
                target_modules=target_modules or "all-linear",
                bias="none",
                task_type="CAUSAL_LM",
            )
            model = get_peft_model(model, peft_config)

        # Load dataset
        job.progress_queue.put(backend_pb2.FineTuneProgressUpdate(
            job_id=job.job_id, status="loading_dataset", message="Loading dataset",
        ))

        dataset_split = request.dataset_split or "train"
        if os.path.exists(request.dataset_source):
            _allowed_dir = os.path.realpath(os.path.abspath(os.environ.get("LOCALAI_DATASET_DIR", os.getcwd())))
            _real_path = os.path.realpath(os.path.abspath(request.dataset_source))
            if not (_real_path == _allowed_dir or _real_path.startswith(_allowed_dir + os.sep)):
                raise ValueError("Dataset source path is outside the allowed directory")
            if request.dataset_source.endswith('.json') or request.dataset_source.endswith('.jsonl'):
                dataset = load_dataset("json", data_files=request.dataset_source, split=dataset_split)
            elif request.dataset_source.endswith('.csv'):
                dataset = load_dataset("csv", data_files=request.dataset_source, split=dataset_split)
            else:
                dataset = load_dataset(request.dataset_source, split=dataset_split)
        else:
            dataset = load_dataset(request.dataset_source, split=dataset_split)

        # Eval dataset setup
        eval_dataset = None
        eval_strategy = extra.get("eval_strategy", "steps")
        eval_steps = int(extra.get("eval_steps", str(request.save_steps if request.save_steps > 0 else 500)))

        if eval_strategy != "no":
            eval_split = extra.get("eval_split")
            eval_dataset_source = extra.get("eval_dataset_source")
            if eval_split:

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Move/copy the dataset under the allowed directory, or set LOCALAI_DATASET_DIR on the backend to the directory containing the dataset and restart.
  2. Send a dataset_source relative to the allowed dir (e.g. 'mydata.jsonl') so the resolved path falls inside it.
  3. If the path uses a symlink, replace it with a bind mount / real directory under the allowed root.

Example fix

# before
LOCALAI_DATASET_DIR unset; request.dataset_source = "/host/datasets/train.jsonl"
# after
# backend env: LOCALAI_DATASET_DIR=/data  (dataset mounted at /data)
request.dataset_source = "/data/train.jsonl"
Defensive patterns

Strategy: validation

Validate before calling

import os

def dataset_path_allowed(source: str, env_var: str = "LOCALAI_DATASET_DIR") -> bool:
    if not os.path.exists(source):
        return True  # hub id path, no local check
    allowed = os.path.realpath(os.path.abspath(os.environ.get(env_var, os.getcwd())))
    real = os.path.realpath(os.path.abspath(source))
    return real == allowed or real.startswith(allowed + os.sep)

Try / catch

try:
    start_finetune(request)
except ValueError as e:
    if "outside the allowed directory" in str(e):
        return error_response(str(e), hint=f"set {env_var} or place files under it")
    raise

Prevention

When it happens

Trigger: Sending a FineTune request with dataset_source='/etc/data.json' while the allowed dir is '/data'; using a symlink inside the sandbox that resolves outside it; running the backend without LOCALAI_DATASET_DIR set so only its working directory is allowed.

Common situations: Operator mounts datasets at a path but forgets to set LOCALAI_DATASET_DIR; client sends host-absolute paths that do not match container paths; symlinked dataset folders.

Related errors


AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15). Data as JSON: /api/errors/210a47d9ba06f41d. Report an issue: GitHub.