{"record":{"id":"78aa7d9adf7f5386","repo":"unslothai/unsloth","slug":"save-directory-must-not-be-empty","errorCode":null,"errorMessage":"save_directory must not be empty","messagePattern":"save_directory must not be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"studio/backend/models/export.py","lineNumber":18,"sourceCode":"# SPDX-License-Identifier: AGPL-3.0-only\n# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0\n\n\"\"\"Pydantic schemas for Export API.\"\"\"\n\nfrom pathlib import Path, PureWindowsPath\n\nfrom pydantic import BaseModel, Field, field_validator\nfrom typing import List, Optional, Literal, Dict, Any, Union\n\n\ndef _validate_save_directory(value: str) -> str:\n    \"\"\"Validate save_directory — allows absolute paths (user may want a different drive).\"\"\"\n    if value is None:\n        raise ValueError(\"save_directory is required\")\n    raw = str(value).strip()\n    if not raw:\n        raise ValueError(\"save_directory must not be empty\")\n    if \"\\x00\" in raw:\n        raise ValueError(\"save_directory may not contain null bytes\")\n    if any(ch in raw for ch in (\"\\r\", \"\\n\")):\n        raise ValueError(\"save_directory may not contain control characters\")\n    path = Path(raw).expanduser()\n    path_parts = (*path.parts, *PureWindowsPath(raw).parts, *raw.replace(\"\\\\\", \"/\").split(\"/\"))\n    if any(len(part) > 255 for part in path_parts if part not in (\"\", \".\", \"/\", \"\\\\\")):\n        raise ValueError(\"save_directory path components must be <= 255 characters\")\n    if (\n        \"..\" in path.parts\n        or \"..\" in PureWindowsPath(raw).parts\n        or \"..\" in raw.replace(\"\\\\\", \"/\").split(\"/\")\n    ):\n        raise ValueError(\"save_directory may not contain '..' segments\")\n    return raw\n\n\nclass LoadCheckpointRequest(BaseModel):","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/models/export.py#L1-L36","documentation":"ValueError from _validate_save_directory when the value is present but strips to an empty string (None was already handled by the preceding check). The validator strips whitespace before testing, so a value of only spaces fails here too.","triggerScenarios":"Sending save_directory as \"\" or \"   \" — e.g. an empty form field serialized verbatim, or a templated value like \"${EXPORT_DIR}\" that resolved to empty.","commonSituations":"UI text input left blank and submitted without client-side required validation; env-var interpolation producing an empty string in generated payloads.","solutions":["Populate save_directory with a real destination path before submitting.","Add client-side validation requiring a non-blank value.","Check template/env interpolation if the value is generated."],"exampleFix":"// before\n{ \"save_directory\": \"\" }\n// after\n{ \"save_directory\": \"/exports/model\" }","handlingStrategy":"validation","validationCode":"def save_directory_nonempty(payload: dict) -> bool:\n    v = payload.get(\"save_directory\")\n    return isinstance(v, str) and v.strip() != \"\"","typeGuard":"def is_nonblank_save_directory(v) -> bool:\n    return isinstance(v, str) and v.strip() != \"\"","tryCatchPattern":null,"preventionTips":["Require a non-blank value in the export form before enabling submit.","Check env-var interpolation when the payload is templated — empty resolution is common.","Trim the value client-side; note the server strips before checking."],"tags":["validation","export","api","http-422","filesystem"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}