{"record":{"id":"7a364807f96c57a7","repo":"unslothai/unsloth","slug":"str-e","errorCode":null,"errorMessage":"str(e)","messagePattern":"str\\(e\\)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/training.py","lineNumber":2755,"sourceCode":"        out_dir = resolve_output_dir(config[\"output_dir\"])\n        if Path(out_dir).resolve() == root:\n            raise HTTPException(\n                status_code = 400,\n                detail = (\n                    f\"'{config['output_dir']}' is the outputs folder itself, not a run inside it. \"\n                    \"Pick a name for this run.\"\n                ),\n            )\n        config[\"output_dir\"] = str(out_dir)\n        # The persistent conditioning cache is another trainer-written directory, so it gets the same containment. Blank/None means the in-memory cache, so it must not resolve to the outputs root.\n        cond_cache = str(config.get(\"cond_cache_dir\") or \"\").strip()\n        cond_cache_dir = resolve_output_dir(cond_cache) if cond_cache else None\n        # Same collapse, but the cache has an honest \"off\" to fall back to: one flat safetensors per cached latent in the trained-models directory is never what was meant.\n        if cond_cache_dir is not None and Path(cond_cache_dir).resolve() == root:\n            cond_cache_dir = None\n        config[\"cond_cache_dir\"] = str(cond_cache_dir) if cond_cache_dir is not None else None\n    except ValueError as e:\n        raise HTTPException(status_code = 400, detail = str(e))\n\n    # Validate the config BEFORE freeing resident GPU workloads, so a refused start never tears down the user's chat/Images model. service.start() re-runs this before spawn.\n    from core.training.diffusion_lora_trainer import _config_from_dict\n\n    try:\n        normalized_cfg = _config_from_dict(config).normalized()\n    except ValueError as e:\n        raise HTTPException(status_code = 400, detail = str(e))\n\n    # Only the DiT trainer reads cond_cache_dir; the SDXL trainer's latent cache is per-process\n    # and in-memory. Checked against the RESOLVED family, not the request field.\n    if cond_cache and normalized_cfg.resolved_family == \"sdxl\":\n        raise HTTPException(\n            status_code = 400,\n            detail = (\n                \"cond_cache_dir is not supported for the sdxl family: its trainer uses a \"\n                \"per-run in-memory latent cache and would ignore the persistent one. Omit it, \"\n                \"or train a DiT family (flux.1, flux.2-klein, flux.2-dev, qwen-image, \"","sourceCodeStart":2737,"sourceCodeEnd":2773,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/training.py#L2737-L2773","documentation":"HTTP 400 with the raw ValueError message from the path-resolution block of the diffusion start route: _resolve_diffusion_data_dir / resolve_output_dir raise ValueError when the dataset dir or output dir fails containment/normalization rules (e.g. escapes the workspace via '..' or absolute paths pointing outside allowed roots, or malformed names). The detail is the exception's own text.","triggerScenarios":"POST diffusion training start with data_dir or output_dir containing traversal segments ('../'), disallowed absolute paths, or otherwise unresolvable values under utils.paths resolution rules.","commonSituations":"Config files authored on another machine with absolute paths; users trying to write outputs to an arbitrary filesystem location instead of a run name; '..'-style relative paths copied from a shell workflow.","solutions":["Read the detail text — it names which path and which rule failed.","Use a plain run name for output_dir and a dataset dir under the workspace; avoid '..' and absolute paths.","If an external dataset location is required, import/copy it into the workspace dataset area first."],"exampleFix":"// before\n{\"data_dir\": \"/mnt/nas/datasets/cats\", \"output_dir\": \"../runs/x\"}\n// after\n{\"data_dir\": \"datasets/cats\", \"output_dir\": \"cats-lora-run\"}","handlingStrategy":"validation","validationCode":"function assertSafeRelativePath(p, field) {\n  if (!p || path.isAbsolute(p) || p.split(/[\\\\/\\\\]/).includes('..')) {\n    throw new Error(`${field} must be a workspace-relative path without '..' segments`)\n  }\n}\nassertSafeRelativePath(config.data_dir, 'data_dir')\nassertSafeRelativePath(config.output_dir, 'output_dir')","typeGuard":null,"tryCatchPattern":"try { await startDiffusionTraining(payload) } catch (e) { if (e.status === 400 && e.detail) { showFieldError(e.detail); return } throw e } // detail names the offending path and rule","preventionTips":["Use plain relative names for data_dir/output_dir; never absolute or '..'-containing paths.","Import external datasets into the workspace dataset area rather than pointing data_dir outside.","Validate config paths client-side with the same containment rules before sending."],"tags":["diffusion","paths","containment","validation","http-400"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}