{"record":{"id":"c18f7cf0bb6171b1","repo":"abi/screenshot-to-code","slug":"design-system-name-is-required","errorCode":null,"errorMessage":"Design system name is required","messagePattern":"Design system name is required","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"backend/routes/design_systems.py","lineNumber":45,"sourceCode":"class UpdateDesignSystemRequest(BaseModel):\n    name: str | None = None\n    content: str | None = None\n\n\ndef get_design_systems_file_path() -> Path:\n    data_dir = os.environ.get(\"SCREENSHOT_TO_CODE_DATA_DIR\")\n    base_path = Path(data_dir).expanduser() if data_dir else Path.home() / \".screenshot-to-code\"\n    return base_path / \"design-systems.json\"\n\n\ndef utc_timestamp() -> str:\n    return datetime.now(timezone.utc).isoformat()\n\n\ndef normalize_name(name: str) -> str:\n    normalized = name.strip()\n    if not normalized:\n        raise HTTPException(status_code=400, detail=\"Design system name is required\")\n    return normalized\n\n\ndef parse_design_system(raw_item: Any) -> DesignSystem | None:\n    if not isinstance(raw_item, dict):\n        return None\n\n    try:\n        return DesignSystem(\n            id=str(raw_item[\"id\"]),\n            name=str(raw_item[\"name\"]),\n            content=str(raw_item.get(\"content\", \"\")),\n            createdAt=str(raw_item[\"createdAt\"]),\n            updatedAt=str(raw_item[\"updatedAt\"]),\n        )\n    except KeyError:\n        return None\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/routes/design_systems.py#L27-L63","documentation":"Raised by normalize_name() in the design-systems router (400) when a submitted name is empty after stripping whitespace. Every create/update path funnels names through this helper, so a name of \"\" or \"   \" is rejected before any storage access. Design systems must have a non-blank human-readable name.","triggerScenarios":"POST /api/design-systems or PUT /api/design-systems/{id} with a body where name is \"\" or only whitespace, or where the frontend sends an unedited empty form field.","commonSituations":"UI forms submitted without required-field validation; trimming done server-side only; programmatic seeds with missing name keys defaulting to empty strings.","solutions":["Provide a non-empty name, e.g. {\"name\": \"Acme DS\", \"content\": \"...\"}.","Add client-side required-field validation on the name input.","Trim the input in the caller and refuse to submit blank values."],"exampleFix":"# before\nrequests.post(url + \"/api/design-systems\", json={\"name\": \"   \", \"content\": \"...\"})  # 400\n\n# after\nname = \"Acme DS\".strip()\nassert name, \"name must not be blank\"\nrequests.post(url + \"/api/design-systems\", json={\"name\": name, \"content\": \"...\"})","handlingStrategy":"validation","validationCode":"name = (name or \"\").strip()\nif not name:\n    raise ValueError(\"design system name is required\")\nrequests.post(url + \"/api/design-systems\", json={\"name\": name, \"content\": content})","typeGuard":"def is_valid_design_system_name(name: object) -> bool:\n    return isinstance(name, str) and bool(name.strip())","tryCatchPattern":"try:\n    resp = requests.post(url + \"/api/design-systems\", json=payload)\n    resp.raise_for_status()\nexcept requests.HTTPError as e:\n    if e.response is not None and e.response.status_code == 400:\n        raise ValueError(\"submission rejected — check name is non-blank\") from e\n    raise","preventionTips":["Make the name field required in UI forms and trim before submit.","Never send defaults like '' for the name."],"tags":["fastapi","http-400","validation","design-systems"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}