Objective
Catch pydantic.ValidationError raised at service / business-logic call sites and translate it into per-domain BackendAIError subclasses so that bad user payloads return HTTP 400 with human-readable, structured field-level error messages instead of bubbling up as HTTP 500.
Background
Several model_validate() calls in service / GraphQL / handler logic let ValidationError propagate up unhandled. The user receives a generic 500 with a noisy repr of the exception. The goal is to give each call site its own domain error class so the response code, error_code, and message clearly tell the client what went wrong.
Scope
- New domain error classes: InvalidSessionCreationConfig (errors/kernel.py), InvalidResourceOpts (errors/kernel.py), InvalidScalingGroupOpts (errors/resource.py), InvalidManagerConfig (errors/resource.py).
- Shared helper format_pydantic_validation_errors() in common/exception.py producing both a human-readable summary ("body.user.email: invalid email; body.age: must be >= 0") and a structured errors list.
- Wrap call sites: api/rest/session/handler.py V1-V7 CreationConfig (12 sites), services/session/service.py:1574, services/model_serving/services/model_serving.py:622, registry.py:1020, services/model_card/service.py:186, gql_legacy/scaling_group.py:683 and :728, gql_legacy/service_config.py:200.
- Improve common parsing layer message format: common/api_handlers.py decorators preserve location prefix (body / query / header / path); manager/api/utils.py pydantic_params_api_handler keeps all field errors instead of just the first.
- Out of scope: external system response parsing (storage-proxy, agent, appproxy clients), bootstrap config loading, DB row deserialization, internal event serialization.
Acceptance Criteria
- Bad user payloads at all listed call sites return HTTP 400 (not 500).
- Each call site raises its own domain-specific error class with a unique error_type and error_code.
- Response body carries a readable msg summary and a structured data.errors list with loc / msg / type per field.
- pants check, pants lint, and pants fmt all pass on the touched files.
JIRA Issue: BA-5978
Objective
Catch pydantic.ValidationError raised at service / business-logic call sites and translate it into per-domain BackendAIError subclasses so that bad user payloads return HTTP 400 with human-readable, structured field-level error messages instead of bubbling up as HTTP 500.
Background
Several model_validate() calls in service / GraphQL / handler logic let ValidationError propagate up unhandled. The user receives a generic 500 with a noisy repr of the exception. The goal is to give each call site its own domain error class so the response code, error_code, and message clearly tell the client what went wrong.
Scope
Acceptance Criteria
JIRA Issue: BA-5978