{"record":{"id":"e57123190cf1e414","repo":"unslothai/unsloth","slug":"caption-too-long-max-max-caption-chars-charact","errorCode":null,"errorMessage":"Caption too long (max {_MAX_CAPTION_CHARS} characters).","messagePattern":"Caption too long \\(max (.+?) characters\\)\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"studio/backend/routes/training.py","lineNumber":3867,"sourceCode":"    response_model = DiffusionDatasetImageRecord,\n)\nasync def set_diffusion_dataset_caption(\n    name: str,\n    filename: str,\n    body: DiffusionCaptionUpdateRequest,\n    current_subject: str = Depends(get_current_subject),\n    _interlock: None = Depends(diffusion_dataset_interlock),\n):\n    \"\"\"Write (or, when blank, clear) an image's ``.txt`` caption sidecar. Returns the\n    updated image record.\"\"\"\n    _require_diffusion_dataset_mutable()\n    folder = _resolve_dataset_folder(name)\n    image_path = _safe_dataset_image_path(folder, filename)\n    if not image_path.is_file():\n        raise HTTPException(status_code = 404, detail = \"Image not found.\")\n    caption = (body.caption or \"\").strip()\n    if len(caption) > _MAX_CAPTION_CHARS:\n        raise HTTPException(\n            status_code = 400,\n            detail = f\"Caption too long (max {_MAX_CAPTION_CHARS} characters).\",\n        )\n\n    def write() -> DiffusionDatasetImageRecord:\n        sidecar = image_path.with_suffix(\".txt\")\n        if caption:\n            sidecar.write_text(caption, encoding = \"utf-8\")\n            image_path.with_suffix(\".caption\").unlink(missing_ok = True)\n            return _image_record(folder, image_path, _load_metadata_captions(folder))\n        # Blank must actually clear. Unlinking alone would resurface this image's metadata caption,\n        # so write an EMPTY sidecar: reader and trainer treat it as an authoritative tombstone.\n        meta = _load_metadata_captions(folder)\n        try:\n            rel = image_path.relative_to(folder).as_posix()\n        except ValueError:\n            rel = image_path.name\n        if image_path.name in meta or rel in meta:","sourceCodeStart":3849,"sourceCodeEnd":3885,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/training.py#L3849-L3885","documentation":"HTTP 400 from the caption-update route: after stripping, the submitted caption exceeds _MAX_CAPTION_CHARS = 2000 characters. The limit keeps .txt sidecars (which the trainer reads per image) bounded. Blank captions are allowed and mean 'clear'; anything over 2000 chars is rejected before any file write.","triggerScenarios":"POST a caption update whose body.caption.strip() length > 2000 — e.g. pasting a long story/essay, a whole article, or accidentally a base64 blob into the caption field.","commonSituations":"Pasting article-length text into the labeling UI; auto-captioning pipelines that concatenate many tag lists; prompt templates accidentally injected wholesale; multibyte content is counted by characters, not bytes.","solutions":["Shorten the caption to <=2000 characters.","For auto-caption pipelines, truncate per-caption output: caption[:2000].","Prefer tag-style captions (comma-separated tags) over prose; trainer prompt handles tags better anyway."],"exampleFix":"# before\napi.set_caption(name, fname, huge_text)  # 20000 chars -> 400\n# after\nMAX = 2000\napi.set_caption(name, fname, huge_text.strip()[:MAX])","handlingStrategy":"validation","validationCode":"MAX_CAPTION_CHARS = 2000\n\ndef caption_ok(text: str | None) -> bool:\n    return len((text or '').strip()) <= MAX_CAPTION_CHARS","typeGuard":"def is_caption_too_long(exc: HTTPException) -> bool:\n    return exc.status_code == 400 and 'Caption too long' in str(exc.detail)","tryCatchPattern":"try:\n    await api.set_caption(name, fname, cap)\nexcept HTTPStatusError as e:\n    if e.response.status_code == 400 and 'Caption too long' in e.response.text:\n        await api.set_caption(name, fname, cap.strip()[:2000])\n    else:\n        raise","preventionTips":["Enforce maxlength=2000 on caption inputs client-side.","Truncate machine-generated captions at the generator, not at the API.","Remember the limit counts characters after strip()."],"tags":["validation","caption","http-400","fastapi"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}