Repository navigation
Description
What happens
When create_adcp_server_from_platform runs the boot validator (validate_capabilities_response_shape), a schema violation raises:
AdcpError: INVALID_REQUEST / terminal: get_adcp_capabilities response failed boot-time spec validation: response does not conform to protocol/get-adcp-capabilities-response.json. Fix the platform's capabilities declaration ...
The failing fields are in error.details["issues"], as a pointer, message, keyword and schema_path for each issue. A pod log or an uncaught traceback prints only the message, though, so the operator can't tell what failed.
We hit this on adcp 10.0.0b13. A reporting doorbell (media_buy.reporting_delivery.ledger_notification) beside webhook_signing.supported: false broke allOf[13] of the 3.3.0-beta.5 schema, with these issues:
/webhook_signing/supported: value does not match the required constant/webhook_signing/profile:'profile'is a required property/webhook_signing/algorithms:'algorithms'is a required property
Every replica crash-looped for hours, and the log never showed those three lines. We had to reproduce the failure locally to find them.
The same message is raised at request time, from PlatformHandler.get_adcp_capabilities (decisioning/handler.py, where it calls _validate_response_dict for request-scoped capabilities). There it reaches a buyer as INVALID_REQUEST, which is just as opaque.
Where
src/adcp/decisioning/validate_capabilities.py, _validate_response_dict. The schema branch is:
raise _violation(
"response does not conform to protocol/get-adcp-capabilities-response.json",
details={"issues": [...]},
)Proposal
Put the issues in the message itself. For example: up to the first 5 issues as <pointer>: <message>, joined with ; , then and N more when there are more. Keep the full list in details. Also name the schema version the response was validated against, since the rules differ between releases (this one applies from 3.2 on).
... response does not conform to protocol/get-adcp-capabilities-response.json (AdCP 3.3.0-beta.5): /webhook_signing/supported: value does not match the required constant; /webhook_signing/profile: 'profile' is a required property; /webhook_signing/algorithms: 'algorithms' is a required property
Related: misleading chained exception
_invoke_capabilities calls asyncio.run(handler.get_adcp_capabilities()) inside the except RuntimeError: block that follows its asyncio.get_running_loop() probe. Any error the handler raises therefore prints as During handling of the above exception (RuntimeError: no running event loop), another exception occurred. That reads like an event-loop bug and sent us looking at the wrong thing.
Fix: probe first, then call asyncio.run outside the except block:
try:
asyncio.get_running_loop()
except RuntimeError:
running = False
else:
running = True
if running:
cause = RuntimeError("asyncio.run() cannot be called from a running event loop")
raise _running_loop_error(cause) from cause
return asyncio.run(handler.get_adcp_capabilities())Workaround
An adopter can catch AdcpError around serve() and log error.details. The Scope3 embedded sales agent does this now: https://github.com/scope3data/embedded-sales-agent/pull/1230.
Activity