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

  1. Set LOCALAI_OUTPUT_DIR on the backend to the intended export root and restart, then use paths inside it.
  2. Send output_path relative to the allowed dir or as an absolute path under it.
  3. 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

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


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