unslothai/unsloth · error · ValueError
save_directory may not contain control characters
Error message
save_directory may not contain control characters
What it means
ValueError from _validate_save_directory when the path contains carriage-return or line-feed characters. Newlines in paths can corrupt logs, manifests, and shell commands that later consume the export destination (CRLF injection), so they are rejected up front.
Source
Thrown at studio/backend/models/export.py:22
"""Pydantic schemas for Export API."""
from pathlib import Path, PureWindowsPath
from pydantic import BaseModel, Field, field_validator
from typing import List, Optional, Literal, Dict, Any, Union
def _validate_save_directory(value: str) -> str:
"""Validate save_directory — allows absolute paths (user may want a different drive)."""
if value is None:
raise ValueError("save_directory is required")
raw = str(value).strip()
if not raw:
raise ValueError("save_directory must not be empty")
if "\x00" in raw:
raise ValueError("save_directory may not contain null bytes")
if any(ch in raw for ch in ("\r", "\n")):
raise ValueError("save_directory may not contain control characters")
path = Path(raw).expanduser()
path_parts = (*path.parts, *PureWindowsPath(raw).parts, *raw.replace("\\", "/").split("/"))
if any(len(part) > 255 for part in path_parts if part not in ("", ".", "/", "\\")):
raise ValueError("save_directory path components must be <= 255 characters")
if (
".." in path.parts
or ".." in PureWindowsPath(raw).parts
or ".." in raw.replace("\\", "/").split("/")
):
raise ValueError("save_directory may not contain '..' segments")
return raw
class LoadCheckpointRequest(BaseModel):
"""Request for loading a checkpoint into the export backend."""
checkpoint_path: str = Field(..., description = "Path to the checkpoint directory")
max_seq_length: int = Field(View on GitHub (pinned to 203007d190)
Solutions
- Trim newlines/CRs from the path value on the client before sending (value.replace(/[\r\n]/g, '')).
- When pasting paths into config, paste into a single-line field or strip whitespace.
- Treat occurrences in production traffic as suspicious and inspect the source client.
Example fix
// before
{ "save_directory": "/exports/model\n" }
// after
{ "save_directory": "/exports/model" } Defensive patterns
Strategy: validation
Validate before calling
def save_directory_no_control_chars(payload: dict) -> bool:
v = payload.get("save_directory")
return isinstance(v, str) and not any(ch in v for ch in ("\r", "\n")) Type guard
def is_single_line_path(v: str) -> bool:
return isinstance(v, str) and "\r" not in v and "\n" not in v Prevention
- Strip CR/LF from pasted paths client-side (v.replace(/[\r\n]/g, '')).
- Avoid multi-line inputs for path fields in the UI.
- Treat CRLF in path fields as injection attempts when they appear in server traffic.
When it happens
Trigger: Sending save_directory with embedded \r or \n, e.g. "/exports\nrm -rf" or a value pasted from a spreadsheet/terminal that retained a trailing newline before a closing quote.
Common situations: Copy/paste from terminals or docs introducing trailing newlines; malicious CRLF-injection attempts against the export API; CSV/spreadsheet-sourced config values.
Related errors
- save_directory may not contain null bytes
- save_directory may not contain '..' segments
- save_directory is required
- save_directory must not be empty
- save_directory path components must be <= 255 characters
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/4aa8df28da01688a.
Report an issue: GitHub.