mudler/LocalAI · error · ValueError
Output path is outside the allowed directory
Error message
Output path is outside the allowed directory
What it means
ExportModel confines exported model outputs to LOCALAI_OUTPUT_DIR (default: backend cwd) using the same realpath containment check as datasets. An output_path that resolves outside that directory — absolute path elsewhere, '..' traversal, or a symlink escaping it — is rejected before any file is written.
Source
Thrown at backend/python/trl/backend.py:697
)
checkpoints.append(backend_pb2.CheckpointInfo(
path=ckpt_path,
step=step,
epoch=float(epoch),
loss=float(loss),
created_at=created_at,
))
return backend_pb2.ListCheckpointsResponse(checkpoints=checkpoints)
def ExportModel(self, request, context):
export_format = request.export_format or "lora"
output_path = request.output_path
_allowed_output_dir = os.path.realpath(os.path.abspath(os.environ.get("LOCALAI_OUTPUT_DIR", os.getcwd())))
_real_output_path = os.path.realpath(os.path.abspath(output_path))
if not (_real_output_path == _allowed_output_dir or _real_output_path.startswith(_allowed_output_dir + os.sep)):
raise ValueError("Output path is outside the allowed directory")
output_path = _real_output_path
checkpoint_path = request.checkpoint_path
# Extract HF token for gated model access
extra = dict(request.extra_options) if request.extra_options else {}
hf_token = extra.get("hf_token") or os.environ.get("HF_TOKEN")
if not checkpoint_path or not os.path.isdir(checkpoint_path):
return backend_pb2.Result(success=False, message=f"Checkpoint not found: {checkpoint_path}")
os.makedirs(output_path, exist_ok=True)
try:
if export_format == "lora":
# Just copy the adapter files
import shutil
for f in os.listdir(checkpoint_path):
src = os.path.join(checkpoint_path, f)View on GitHub (pinned to 44413a9d06)
Solutions
- Set LOCALAI_OUTPUT_DIR on the backend to the intended export root and restart, then use paths inside it.
- Send output_path relative to the allowed dir or as an absolute path under it.
- Replace symlinks with real directories/mounts under the allowed root.
Example fix
# before LOCALAI_OUTPUT_DIR unset; request.output_path = "/tmp/my-export" # after # backend env: LOCALAI_OUTPUT_DIR=/exports request.output_path = "/exports/my-export"
Defensive patterns
Strategy: validation
Validate before calling
import os
def output_path_allowed(output_path: str) -> bool:
allowed = os.path.realpath(os.path.abspath(os.environ.get("LOCALAI_OUTPUT_DIR", os.getcwd())))
real = os.path.realpath(os.path.abspath(output_path))
return real == allowed or real.startswith(allowed + os.sep) Try / catch
try:
ExportModel(request, context)
except ValueError as e:
if "outside the allowed directory" in str(e):
return Result(success=False, message=str(e) + f"; set LOCALAI_OUTPUT_DIR")
raise Prevention
- Set LOCALAI_OUTPUT_DIR to the exported-models volume and reuse it for every request.
- Construct output paths with os.path.join(allowed_root, name).
- Test export in CI with the same env var as production.
When it happens
Trigger: Calling ExportModel with output_path='/tmp/export' when LOCALAI_OUTPUT_DIR is unset; output_path='../shared/out'; the client using host paths that differ from container paths.
Common situations: Operator exposes an exports volume but does not set LOCALAI_OUTPUT_DIR; CI pipelines writing to arbitrary temp dirs; symlinked output dirs.
Related errors
- Dataset source path is outside the allowed directory
- Inline reward function '{name}' rejected: inline reward code
- model snapshot does not exist: {model_ref}
- model snapshot must contain exactly one {suffix} file; found
- no insightface pack '{self.model_pack}' found — install via
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/61288b2cbf9142c3.
Report an issue: GitHub.