unslothai/unsloth · error · HTTPException
Caption too long (max {_MAX_CAPTION_CHARS} characters).
Error message
Caption too long (max {_MAX_CAPTION_CHARS} characters). What it means
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.
Source
Thrown at studio/backend/routes/training.py:3867
response_model = DiffusionDatasetImageRecord,
)
async def set_diffusion_dataset_caption(
name: str,
filename: str,
body: DiffusionCaptionUpdateRequest,
current_subject: str = Depends(get_current_subject),
_interlock: None = Depends(diffusion_dataset_interlock),
):
"""Write (or, when blank, clear) an image's ``.txt`` caption sidecar. Returns the
updated image record."""
_require_diffusion_dataset_mutable()
folder = _resolve_dataset_folder(name)
image_path = _safe_dataset_image_path(folder, filename)
if not image_path.is_file():
raise HTTPException(status_code = 404, detail = "Image not found.")
caption = (body.caption or "").strip()
if len(caption) > _MAX_CAPTION_CHARS:
raise HTTPException(
status_code = 400,
detail = f"Caption too long (max {_MAX_CAPTION_CHARS} characters).",
)
def write() -> DiffusionDatasetImageRecord:
sidecar = image_path.with_suffix(".txt")
if caption:
sidecar.write_text(caption, encoding = "utf-8")
image_path.with_suffix(".caption").unlink(missing_ok = True)
return _image_record(folder, image_path, _load_metadata_captions(folder))
# Blank must actually clear. Unlinking alone would resurface this image's metadata caption,
# so write an EMPTY sidecar: reader and trainer treat it as an authoritative tombstone.
meta = _load_metadata_captions(folder)
try:
rel = image_path.relative_to(folder).as_posix()
except ValueError:
rel = image_path.name
if image_path.name in meta or rel in meta:View on GitHub (pinned to 203007d190)
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.
Example fix
# before api.set_caption(name, fname, huge_text) # 20000 chars -> 400 # after MAX = 2000 api.set_caption(name, fname, huge_text.strip()[:MAX])
Defensive patterns
Strategy: validation
Validate before calling
MAX_CAPTION_CHARS = 2000
def caption_ok(text: str | None) -> bool:
return len((text or '').strip()) <= MAX_CAPTION_CHARS Type guard
def is_caption_too_long(exc: HTTPException) -> bool:
return exc.status_code == 400 and 'Caption too long' in str(exc.detail) Try / catch
try:
await api.set_caption(name, fname, cap)
except HTTPStatusError as e:
if e.response.status_code == 400 and 'Caption too long' in e.response.text:
await api.set_caption(name, fname, cap.strip()[:2000])
else:
raise Prevention
- 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().
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid image filename.
- Not an image file. Allowed: {exts}
- Invalid repo_id: {repo_id!r}
- Unsupported local dataset directory (expected parquet/json/j
- Unsupported file format: {dataset_path.suffix}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/e57123190cf1e414.
Report an issue: GitHub.