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
- Move/copy the dataset under the allowed directory, or set LOCALAI_DATASET_DIR on the backend to the directory containing the dataset and restart.
- Send a dataset_source relative to the allowed dir (e.g. 'mydata.jsonl') so the resolved path falls inside it.
- 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
- Set LOCALAI_DATASET_DIR explicitly and document it next to the volume mount.
- Send relative dataset paths from clients.
- Avoid symlinks in dataset paths; use bind mounts.
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
- Output path is outside the allowed directory
- Inline reward function '{name}' rejected: inline reward code
- GRPO requires at least one reward function. Specify reward_f
- Unsupported training method: {training_method}. Supported: s
- model snapshot does not exist: {model_ref}
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/210a47d9ba06f41d.
Report an issue: GitHub.