abi/screenshot-to-code · error · HTTPException
Design systems storage must contain a list
Error message
Design systems storage must contain a list
What it means
Raised by read_design_systems() (500) when design-systems.json parses as valid JSON but the top-level value is not a list (e.g. an object like {"items": []}). The storage contract is a JSON array of design-system records; anything else is treated as structural corruption and fails every design-systems endpoint.
Source
Thrown at backend/routes/design_systems.py:79
except KeyError:
return None
def read_design_systems() -> list[DesignSystem]:
file_path = get_design_systems_file_path()
if not file_path.exists():
return []
try:
raw_items = cast(list[Any], json.loads(file_path.read_text(encoding="utf-8")))
except json.JSONDecodeError as exc:
raise HTTPException(
status_code=500,
detail="Design systems storage is not valid JSON",
) from exc
if not isinstance(raw_items, list):
raise HTTPException(
status_code=500,
detail="Design systems storage must contain a list",
)
design_systems: list[DesignSystem] = []
for raw_item in raw_items:
design_system = parse_design_system(raw_item)
if design_system:
design_systems.append(design_system)
return design_systems
def write_design_systems(design_systems: list[DesignSystem]) -> None:
file_path = get_design_systems_file_path()
file_path.parent.mkdir(parents=True, exist_ok=True)
tmp_path = file_path.with_suffix(".json.tmp")
serialized = json.dumps(
[design_system.model_dump() for design_system in design_systems],View on GitHub (pinned to d026163f58)
Solutions
- Rewrite the file as a top-level JSON array of records: [{"id": ..., "name": ..., "content": ..., "createdAt": ..., "updatedAt": ...}, ...].
- If you need the data, extract the inner list from the wrapper object and save it as the top level.
- Reset with '[]' if the contents are disposable.
- Verify with python -c "import json;print(type(json.load(open(<path>))))" -> should print <class 'list'>.
Example fix
# before: {"designSystems": [{"id": "1", "name": "DS"}]}
GET /api/design-systems # 500
# after: [{"id": "1", "name": "DS", "content": "", "createdAt": "...", "updatedAt": "..."}] Defensive patterns
Strategy: validation
Validate before calling
import json
def design_store_is_list(path: str) -> bool:
try:
return isinstance(json.loads(open(path, encoding="utf-8").read()), list)
except (OSError, json.JSONDecodeError):
return False Type guard
def is_design_store_shape(value: object) -> bool:
return isinstance(value, list) Try / catch
try:
systems = requests.get(url + "/api/design-systems").raise_for_status().json()
except requests.HTTPError as e:
if e.response is not None and "must contain a list" in e.response.text:
raise RuntimeError("storage schema wrong: top level must be a JSON array") from e
raise Prevention
- Keep design-systems.json a top-level array of record objects.
- If wrapping data, unwrap it back to an array before restarting the backend.
- Automate backups so a schema mistake is recoverable.
When it happens
Trigger: Any /api/design-systems call after the file was replaced with a dict, a bare string, or a number — typically from a hand edit or an external tool writing a different schema.
Common situations: Users wrap the array in an object for 'readability'; migration scripts export a different shape; the file was overwritten by another application.
Related errors
- Design systems storage is not valid JSON
- Unreadable briefs.json for {set_name}: {exc}
- Design system name is required
- Design system not found
- Error reading input files: {str(e)}
AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14).
Data as JSON: /api/errors/7c4c77eebb2839ac.
Report an issue: GitHub.