What happens
The target manager container's HTTP API is the documented way for Docker users to configure the mock — docs/source/docker.rst shows a curl call against POST /cloud_databases and documents the accepted JSON fields. That API does not validate its input, so a wrong value produces a 500 rather than a useful error.
Probing it directly:
valid empty body -> 201
bad state_name -> 500
bad state_name casing -> 500
bad database_type_name -> 500
request_rate_limits malformed -> 500
request_rate_limits wrong type -> 500
request_quota is a string -> 500
delete unknown database -> 404
target on unknown database -> 500
vumark target unknown db -> 500
The underlying exceptions:
KeyError: 'inactive' # state_name
KeyError: 'project_inactive' # state_name, wrong case
KeyError: 'cloud' # database_type_name
KeyError: 'window_seconds' # request_rate_limits entry missing a key
ValueError: not enough values to unpack # target on an unknown database
beartype...BeartypeCallHintParamViolation: ... RequestRateLimits.from_dict ...
beartype...BeartypeCallHintParamViolation: ... CloudDatabase.__init__() parameter request_quota ...
create_cloud_database does States[state_name] and DatabaseType[database_type_name] on unvalidated input, passes unvalidated values straight into CloudDatabase(...) where beartype rejects them, and calls RequestRateLimits.from_dict on whatever was supplied.
Why it matters
{"state_name": "inactive"} is a very easy thing to send. docs/source/docker.rst documents the valid values as WORKING, PROJECT_INACTIVE, PROJECT_SUSPENDED and PROJECT_HAS_NO_API_ACCESS, but a user who lowercases one gets an empty 500 with nothing naming the field or the accepted values. The same applies to database_type_name and to any request_rate_limits object which is not exactly right — and request_rate_limits has the most structure of any field here, so it is the one most likely to be got wrong.
This API is also the piece of the project a non-Python user interacts with most directly. They cannot read the States enum to work out what was wrong.
The handling is not uniformly missing, which is the encouraging part: delete_cloud_database and delete_vumark_database already catch the not-found case and return 404. The pattern exists; it is just not applied to the create routes.
Suggested resolution
Validate the request body and return a 400 which names the offending field and the accepted values.
The project already depends on pydantic-settings, and pydantic is already configured for mypy in pyproject.toml, so declaring a pydantic model for the create-database body would give field-level errors, correct types and a serialisable error response without new dependencies. That also removes the hand-written request_json.get(field, random_database.field) chain, which is currently how defaults are applied.
create_target and create_vumark_target should return 404 for an unknown database name, matching what delete_cloud_database already does, rather than letting the single-element unpack raise. Those two are reached by the VWS container as well as by users, so a clear 404 also makes a misconfigured deployment easier to diagnose.
Related to #3392 in kind — unvalidated input reaching code which assumes it is well formed — but on a different API, with a different audience, and a different fix.
What happens
The target manager container's HTTP API is the documented way for Docker users to configure the mock —
docs/source/docker.rstshows acurlcall againstPOST /cloud_databasesand documents the accepted JSON fields. That API does not validate its input, so a wrong value produces a 500 rather than a useful error.Probing it directly:
The underlying exceptions:
create_cloud_databasedoesStates[state_name]andDatabaseType[database_type_name]on unvalidated input, passes unvalidated values straight intoCloudDatabase(...)where beartype rejects them, and callsRequestRateLimits.from_dicton whatever was supplied.Why it matters
{"state_name": "inactive"}is a very easy thing to send.docs/source/docker.rstdocuments the valid values asWORKING,PROJECT_INACTIVE,PROJECT_SUSPENDEDandPROJECT_HAS_NO_API_ACCESS, but a user who lowercases one gets an empty 500 with nothing naming the field or the accepted values. The same applies todatabase_type_nameand to anyrequest_rate_limitsobject which is not exactly right — andrequest_rate_limitshas the most structure of any field here, so it is the one most likely to be got wrong.This API is also the piece of the project a non-Python user interacts with most directly. They cannot read the
Statesenum to work out what was wrong.The handling is not uniformly missing, which is the encouraging part:
delete_cloud_databaseanddelete_vumark_databasealready catch the not-found case and return 404. The pattern exists; it is just not applied to the create routes.Suggested resolution
Validate the request body and return a 400 which names the offending field and the accepted values.
The project already depends on pydantic-settings, and pydantic is already configured for mypy in
pyproject.toml, so declaring a pydantic model for the create-database body would give field-level errors, correct types and a serialisable error response without new dependencies. That also removes the hand-writtenrequest_json.get(field, random_database.field)chain, which is currently how defaults are applied.create_targetandcreate_vumark_targetshould return 404 for an unknown database name, matching whatdelete_cloud_databasealready does, rather than letting the single-element unpack raise. Those two are reached by the VWS container as well as by users, so a clear 404 also makes a misconfigured deployment easier to diagnose.Related to #3392 in kind — unvalidated input reaching code which assumes it is well formed — but on a different API, with a different audience, and a different fix.