feat(api): standardize V3 error status codes and documentation

- Updated V3 CRUD routers to return 400 Bad Request for database schema
  errors (unknown columns) across all list and search endpoints.
- Fixed serialization issue in nested patch endpoint.
- Overhauled Section 7 of Frontend Integration Guide to document HTTP
  status code mappings for common error categories.
This commit is contained in:
Scott Idem
2026-01-29 18:18:04 -05:00
parent b862d59e65
commit 5d91c05925
3 changed files with 22 additions and 6 deletions

View File

@@ -262,6 +262,15 @@ async def get_obj_li(
as_list=True, as_list=True,
) )
if sql_result is False:
# Standardized rich error bubbling
db_err = format_db_error(get_last_sql_error())
# If it's a schema error (like Unknown Column), it's a 400 Bad Request
status_code = 400 if db_err.category == "database_schema" else 500
return mk_resp(data=False, status_code=status_code, response=response, status_message="Listing failed due to database error.", details=db_err.dict())
if sql_result: if sql_result:
resp_data_li = [base_name(**record).dict(by_alias=serialization.by_alias, exclude_unset=serialization.exclude_unset, exclude_defaults=serialization.exclude_defaults, exclude_none=serialization.exclude_none) for record in sql_result] resp_data_li = [base_name(**record).dict(by_alias=serialization.by_alias, exclude_unset=serialization.exclude_unset, exclude_defaults=serialization.exclude_defaults, exclude_none=serialization.exclude_none) for record in sql_result]
return mk_resp(data=resp_data_li, response=response) return mk_resp(data=resp_data_li, response=response)

View File

@@ -310,7 +310,7 @@ async def patch_child_obj(
return mk_resp(data=True, response=response, status_message="Updated successfully.") return mk_resp(data=True, response=response, status_message="Updated successfully.")
else: else:
db_err = format_db_error(get_last_sql_error()) db_err = format_db_error(get_last_sql_error())
return mk_resp(data=False, status_code=400, response=response, status_message="Update failed.", details=db_err) return mk_resp(data=False, status_code=400, response=response, status_message="Update failed.", details=db_err.dict())
@router.delete('/{parent_obj_type}/{parent_obj_id}/{child_obj_type}/{child_obj_id}', response_model=Resp_Body_Base) @router.delete('/{parent_obj_type}/{parent_obj_id}/{child_obj_type}/{child_obj_id}', response_model=Resp_Body_Base)

View File

@@ -132,11 +132,18 @@ V3 uses a **String-Only ID Vision**. The frontend NEVER handles or stores databa
V3 returns machine-readable error objects in `meta.details` for failures. V3 returns machine-readable error objects in `meta.details` for failures.
**Common Categories:** ### HTTP Status Codes
- `database_duplicate`: Non-unique value (Code 1062). - **`400 Bad Request`**: Used for client-driven errors including invalid search fields, validation failures, and constraint violations.
- `database_constraint`: Foreign key violation (Codes 1451, 1452). - **`403 Forbidden`**: Missing or invalid API Key / Account Context.
- `database_schema`: Invalid column name (Codes 1054, 1146). - **`404 Not Found`**: Object ID does not exist.
- `validation`: Pydantic validation failed (Check `details` for field-specific errors). - **`500 Internal Server Error`**: Unexpected server crash or database connection failure.
### Common Error Categories
Found in `meta.details.category`:
- `database_duplicate`: Non-unique value (Code 1062). -> **400**
- `database_constraint`: Foreign key violation (Codes 1451, 1452). -> **400**
- `database_schema`: Invalid column name or missing field in the requested `view` (Codes 1054, 1146). -> **400**
- `validation`: Pydantic validation failed (Check `details` for field-specific errors). -> **400**
--- ---