OpenAPI documentation for custom DecodeFailureHandler

Hi, my application returns errors in a standardized format, a class com.example.Fail. I’m using TapirJsonCirce to derive a Codec and a Schema for it. When I specify this error type in the endpoint and then explicitly return it as error in the endpoints, everything works as expected. I get a nice error message from the API that is correctly documented in OpenAPI.

I’ve gone a step further and defined a custom DecodeFailureHandler so that all decode failures are also returned in this error format. As far as the API goes, it works perfectly, and when I send an bad request, my request is handled by the code I’ve written, and I get a nice com.example.Fail response like:

{"errors":[{"code":"INVALID_PATH_PARAM","message":"Invalid value for: path parameter item-id: Some(UUID string too large)"}],"timestamp":1674737764093}

I’ve figured out that in order to correctly document these responses in the OpenAPI documentation, I need to also configure defaultDecodeFailureOutput: EndpointInput[_] => Option[EndpointOutput[_]] in OpenAPIDocsOptions. I’ve made it return something like:

Some(statusCode(StatusCode.BadRequest) and jsonBody[com.example.Fail])

This almost works. The OpenAPI doc picks up the new response (and I can successfully set descriptions and examples), but the schema is broken. The $ref contains the class name instead of a reference to the correct type:

'400':
  content:
    application/json:
      schema:
        $ref: com.example.Fail

instead of:

'400':
  content:
    application/json:
      schema:
        $ref: '#/components/schemas/Fail'

I’ve used SwaggerInterpreter’s customiseDocsModel to manually fix the references but that’s hacky. Is there something else I can do to fix this?

Indeed, good catch, this was a bug. PR fixing this is here: Properly generate docs for default error responses defined in options by adamw · Pull Request #2717 · softwaremill/tapir · GitHub