{"record":{"id":"088e2d417a228f47","repo":"Comfy-Org/ComfyUI","slug":"bboxes-string-input-is-not-valid-json-exc-088e2d","errorCode":null,"errorMessage":"bboxes string input is not valid JSON: {exc}","messagePattern":"bboxes string input is not valid JSON: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_extras/nodes_compositor.py","lineNumber":73,"sourceCode":"    w, h = _int(canvas[0], 0), _int(canvas[1], 0)\n    return (w, h) if w > 0 and h > 0 else None\n\n\ndef _int(value, default: int) -> int:\n    return int(value) if isinstance(value, (int, float)) and not isinstance(value, bool) else default\n\n\ndef _bbox_list(bboxes, canvas_width: int, canvas_height: int) -> list[dict]:\n    if bboxes is None:\n        return []\n    if isinstance(bboxes, str):\n        text = bboxes.strip()\n        if not text:\n            return []\n        try:\n            bboxes = json.loads(text)\n        except (json.JSONDecodeError, ValueError) as exc:\n            raise ValueError(f\"bboxes string input is not valid JSON: {exc}\") from exc\n    probe = bboxes if isinstance(bboxes, list) else [bboxes]\n    if probe and isinstance(probe[0], list):\n        probe = probe[0]\n    has_elements = any(\n        isinstance(box, dict) and isinstance(box.get(\"bbox\"), (list, tuple))\n        for box in probe\n    )\n    if has_elements and (canvas_width <= 0 or canvas_height <= 0):\n        raise ValueError(\n            \"normalized element boxes need canvas_width and canvas_height to resolve to pixels\"\n        )\n    return boxes_from_input(bboxes, canvas_width, canvas_height)\n\n\ndef _item_mask_frame(mask, index: int) -> torch.Tensor | None:\n    if not isinstance(mask, torch.Tensor):\n        return None\n    if mask.shape[0] == 1:","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_extras/nodes_compositor.py#L55-L91","documentation":"The compositor's `_bbox_list` accepts the bboxes input either as a Python list or as a JSON string. When a string is given, it is stripped and parsed with json.loads; if parsing fails (JSONDecodeError or ValueError) the parser re-raises with this message including the underlying parse error. Only a completely empty/whitespace string is treated as 'no boxes'.","triggerScenarios":"Wiring a text widget or LLM/text output into bboxes that is not valid JSON, e.g. \"[[10, 10, 50, 50],\" (truncated), \"(10, 10, 50, 50)\" (Python repr, not JSON), or text with leading prose like 'Here are the boxes: [...]'.","commonSituations":"Pasting Python-style lists with single quotes ('[[0,0,10,10]]' is invalid JSON because of quote style); truncated API responses; agent-generated text that wraps JSON in markdown fences or commentary instead of raw JSON.","solutions":["Send strict JSON: double quotes, no trailing commas, complete brackets.","Strip markdown fences and any surrounding prose so the string is pure JSON.","Replace single-quoted Python reprs with properly serialized JSON (json.dumps on the Python side).","If the widget content is optional, leave it empty rather than partially edited."],"exampleFix":"// before\nbboxes = \"[[0, 0, 10, 10], [20, 20, 30, 30]]\"  // or a truncated string\n// after\nbboxes = \"[[0, 0, 10, 10], [20, 20, 30, 30]]\"","handlingStrategy":"validation","validationCode":"import json\ndef parse_bbox_string(s: str):\n    s = s.strip()\n    if s.startswith(\"```\"):\n        s = s.strip(\"`\").lstrip(\"json\").strip()\n    if not s:\n        return []\n    return json.loads(s)  # let JSONDecodeError surface clearly","typeGuard":"def is_json_string(s) -> bool:\n    if not isinstance(s, str) or not s.strip():\n        return False\n    try:\n        json.loads(s)\n        return True\n    except (json.JSONDecodeError, ValueError):\n        return False","tryCatchPattern":"try:\n    boxes = json.loads(text)\nexcept json.JSONDecodeError as exc:\n    raise ValueError(f\"model output was not valid JSON boxes: {exc}\") from exc","preventionTips":["Always serialize with json.dumps rather than str() of a Python list.","Strip markdown fences and prose from LLM output before parsing.","Prefer passing native lists instead of strings when the input permits."],"tags":["json","validation","bounding-boxes","comfyui"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}