{"record":{"id":"846f71e6e2fef74d","repo":"unslothai/unsloth","slug":"cond-cache-dir-is-not-supported-for-the-sdxl-famil","errorCode":null,"errorMessage":"cond_cache_dir is not supported for the sdxl family: its trainer uses a per-run in-memory latent cache and would ignore the persistent one. Omit it, or train a DiT family (flux.1, flux.2-klein, flux.2-dev, qwen-image, z-image, krea-2), which reuses conditioning across runs.","messagePattern":"cond_cache_dir is not supported for the sdxl family: its trainer uses a per-run in-memory latent cache and would ignore the persistent one\\. Omit it, or train a DiT family \\(flux\\.1, flux\\.2-klein, flux\\.2-dev, qwen-image, z-image, krea-2\\), which reuses conditioning across runs\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/training.py","lineNumber":2768,"sourceCode":"        # 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, \"\n                \"z-image, krea-2), which reuses conditioning across runs.\"\n            ),\n        )\n\n    # Same rule for the MiniMax-H3 trainer's own restrictions, which are config-only and so\n    # answerable here: a batch > 1, a non-bf16 precision, a weighting scheme, a compile\n    # request or a conditioning-cache directory used to reach the worker and 400 there, with\n    # the user's resident models already evicted for a run that never started.\n    from core.training.diffusion_train_common import h3_train_unsupported_reason\n\n    _h3_reason = h3_train_unsupported_reason(normalized_cfg)\n    if _h3_reason:\n        raise HTTPException(status_code = 400, detail = _h3_reason)","sourceCodeStart":2750,"sourceCodeEnd":2786,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/training.py#L2750-L2786","documentation":"HTTP 400 on diffusion training start: the request sets cond_cache_dir (persistent conditioning/latent cache) but the RESOLVED model family is 'sdxl', whose trainer uses a per-run in-memory latent cache and would silently ignore the persistent one. The check uses normalized_cfg.resolved_family (what the trainer will actually run), not the raw request field, so aliases that resolve to SDXL are caught too. The error lists the DiT families that do support it (flux.1, flux.2-klein, flux.2-dev, qwen-image, z-image, krea-2).","triggerScenarios":"POST diffusion training start with cond_cache_dir set and a model that resolves to the sdxl family (including aliased or shorthand model names that resolve to SDXL).","commonSituations":"Copy-pasting a Flux config (which benefits from the conditioning cache across runs) to an SDXL run; UI state retaining the cache field when the user switches model family.","solutions":["Remove/omit cond_cache_dir for SDXL runs — its latent cache is automatic and in-memory.","Or switch the model to a DiT family (flux.1, flux.2-klein, flux.2-dev, qwen-image, z-image, krea-2) to reuse conditioning across runs.","Clear family-specific fields in the client whenever the resolved model family changes."],"exampleFix":"// before\n{\"model\": \"sd-xl-base\", \"cond_cache_dir\": \"cond-cache/\", ...}\n// after (sdxl: omit it)\n{\"model\": \"sd-xl-base\", ...}\n// after (keep the cache: use a DiT family)\n{\"model\": \"flux.1-dev\", \"cond_cache_dir\": \"cond-cache/\", ...}","handlingStrategy":"validation","validationCode":"const SDXL_HINTS = /sdxl|sd-xl|sd_xl/i\nfunction isSdxl(model) { return SDXL_HINTS.test(model) }\nif (config.cond_cache_dir && isSdxl(config.model)) {\n  delete config.cond_cache_dir // sdxl uses a per-run in-memory latent cache\n}","typeGuard":"function supportsCondCache(resolvedFamily) {\n  return ['flux.1', 'flux.2-klein', 'flux.2-dev', 'qwen-image', 'z-image', 'krea-2']\n    .includes(resolvedFamily)\n}","tryCatchPattern":"try { await startDiffusionTraining(payload) } catch (e) { if (e.status === 400 && /cond_cache_dir is not supported for the sdxl family/.test(e.detail)) { delete payload.cond_cache_dir; return startDiffusionTraining(payload) } throw e }","preventionTips":["Clear cond_cache_dir whenever the selected model resolves to the SDXL family.","Remember the check uses the RESOLVED family — aliases that resolve to SDXL are caught too.","Only carry cond_cache_dir over between runs of DiT families (flux, qwen-image, z-image, krea-2)."],"tags":["diffusion","sdxl","cond-cache","config","validation","http-400"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}