abi/screenshot-to-code · error · HTTPException

Design system name is required

Error message

Design system name is required

What it means

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.

Source

Thrown at backend/routes/design_systems.py:45

class UpdateDesignSystemRequest(BaseModel):
    name: str | None = None
    content: str | None = None


def get_design_systems_file_path() -> Path:
    data_dir = os.environ.get("SCREENSHOT_TO_CODE_DATA_DIR")
    base_path = Path(data_dir).expanduser() if data_dir else Path.home() / ".screenshot-to-code"
    return base_path / "design-systems.json"


def utc_timestamp() -> str:
    return datetime.now(timezone.utc).isoformat()


def normalize_name(name: str) -> str:
    normalized = name.strip()
    if not normalized:
        raise HTTPException(status_code=400, detail="Design system name is required")
    return normalized


def parse_design_system(raw_item: Any) -> DesignSystem | None:
    if not isinstance(raw_item, dict):
        return None

    try:
        return DesignSystem(
            id=str(raw_item["id"]),
            name=str(raw_item["name"]),
            content=str(raw_item.get("content", "")),
            createdAt=str(raw_item["createdAt"]),
            updatedAt=str(raw_item["updatedAt"]),
        )
    except KeyError:
        return None

View on GitHub (pinned to d026163f58)

Solutions

  1. Provide a non-empty name, e.g. {"name": "Acme DS", "content": "..."}.
  2. Add client-side required-field validation on the name input.
  3. Trim the input in the caller and refuse to submit blank values.

Example fix

# before
requests.post(url + "/api/design-systems", json={"name": "   ", "content": "..."})  # 400

# after
name = "Acme DS".strip()
assert name, "name must not be blank"
requests.post(url + "/api/design-systems", json={"name": name, "content": "..."})
Defensive patterns

Strategy: validation

Validate before calling

name = (name or "").strip()
if not name:
    raise ValueError("design system name is required")
requests.post(url + "/api/design-systems", json={"name": name, "content": content})

Type guard

def is_valid_design_system_name(name: object) -> bool:
    return isinstance(name, str) and bool(name.strip())

Try / catch

try:
    resp = requests.post(url + "/api/design-systems", json=payload)
    resp.raise_for_status()
except requests.HTTPError as e:
    if e.response is not None and e.response.status_code == 400:
        raise ValueError("submission rejected — check name is non-blank") from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: UI forms submitted without required-field validation; trimming done server-side only; programmatic seeds with missing name keys defaulting to empty strings.

Related errors


AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14). Data as JSON: /api/errors/c18f7cf0bb6171b1. Report an issue: GitHub.