{"record":{"id":"0be9100f1d040696","repo":"Comfy-Org/ComfyUI","slug":"invalid-body-0be910","errorCode":"INVALID_BODY","errorMessage":"Unknown tags: {missing}","messagePattern":"Unknown tags: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"app/assets/database/queries/tags.py","lineNumber":55,"sourceCode":"    total_tags: list[str]\n\n\n@dataclass(frozen=True)\nclass SetTagsResult:\n    added: list[str]\n    removed: list[str]\n    total: list[str]\n\n\ndef validate_tags_exist(session: Session, tags: list[str]) -> None:\n    \"\"\"Raise ValueError if any of the given tag names do not exist.\"\"\"\n    existing_tag_names = set(\n        name\n        for (name,) in session.execute(select(Tag.name).where(Tag.name.in_(tags))).all()\n    )\n    missing = [t for t in tags if t not in existing_tag_names]\n    if missing:\n        raise ValueError(f\"Unknown tags: {missing}\")\n\n\ndef ensure_tags_exist(session: Session, names: Iterable[str]) -> None:\n    wanted = normalize_tags(list(names))\n    if not wanted:\n        return\n    rows = [{\"name\": n} for n in list(dict.fromkeys(wanted))]\n    ins = (\n        sqlite.insert(Tag)\n        .values(rows)\n        .on_conflict_do_nothing(index_elements=[Tag.name])\n    )\n    session.execute(ins)\n\n\ndef get_reference_tags(session: Session, reference_id: str) -> list[str]:\n    return [\n        tag_name","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/app/assets/database/queries/tags.py#L37-L73","documentation":"ValueError raised by validate_tags_exist when any requested tag names are absent from the Tag table. It queries Tag.name IN (tags) and reports every missing name in the message, so the error doubles as a report of exactly which tags need creating.","triggerScenarios":"Calling add_tags_to_reference (or any tag path) with create_if_missing=False after the tags were never created, or with names that normalize differently than how they were stored (case/whitespace). Also triggered by direct validate_tags_exist calls in API request validation.","commonSituations":"Clients sending free-form tag strings to an endpoint that requires pre-existing tags; tags created in one environment and expected in another; whitespace or case variants ('Sketch ' vs 'sketch') that miss the stored name because normalization differs between write and validate paths.","solutions":["Create the tags first with ensure_tags_exist (or pass create_if_missing=True in add_tags_to_reference).","Normalize tag names the same way the writers do (strip + case handling per normalize_tags) before validating.","Parse the missing list from the error message and offer tag creation to the user.","Map this ValueError to 400 INVALID_BODY at the API boundary since it indicates a bad request payload."],"exampleFix":"// before\nadd_tags_to_reference(session, rid, [\"ink\", \"sketch \"], create_if_missing=False)\n\n// after\nfrom app.assets.database.queries.tags import ensure_tags_exist\nwanted = normalize_tags([\"ink\", \"sketch \"])\nensure_tags_exist(session, wanted)\nadd_tags_to_reference(session, rid, wanted, create_if_missing=False)","handlingStrategy":"validation","validationCode":"from app.assets.database.queries.tags import normalize_tags\n\ndef tags_are_known(session, tags: list[str]) -> bool:\n    wanted = normalize_tags(tags)\n    existing = {n for (n,) in session.execute(select(Tag.name).where(Tag.name.in_(wanted))).all()}\n    return set(wanted) <= existing","typeGuard":null,"tryCatchPattern":"try:\n    add_tags_to_reference(session, rid, tags, create_if_missing=False)\nexcept ValueError as e:\n    # message lists the missing names; map to 400 INVALID_BODY\n    raise HTTPException(status_code=400, detail=str(e))","preventionTips":["Pre-create tags with ensure_tags_exist, or use create_if_missing=True when auto-creation is acceptable.","Normalize tag names identically on write and validate paths (use normalize_tags).","Parse the missing list from the message to prompt the user."],"tags":["tags","database","validation","bad-request"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}