# Tapir-redoc annotations not working as expected

**URL:** <https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289>\
**Category:** tapir\
**Created:** [October 2, 2023, 1:22pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289 "2023-10-02T13:22:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 2, 2023, 1:22pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/1 "2023-10-02T13:22:54Z")

</div>

Hello Guys,

Something about Tapir annotations with Redoc is not working as I would expect:

When annotating attributes with `@Schema.annotation.deprecated` it mostly gets picked up.

But when a case class is used for another attribute, it switches to using a `$ref` to a Schema. Which makes sense for the case class structure, but not for the deprecation.  
Which will then have all attributes of the type deprecated or none of them!?

Eg in this SSCCE based on zip generatd with `adopt-tapir.softwaremill.com`:

> <https://github.com/andersbohn/tapir-redoc-issue/pull/2>

```auto
  case class Book(
      title: String,
      year: Int,
      a1: CcA,
      a2: CcA,
      @Schema.annotations.deprecated b1: CcB,
      b2: CcB,
      c1: CcC,
      @Schema.annotations.deprecated c2: CcC,
      @Schema.annotations.deprecated d1: CcD,
      @Schema.annotations.deprecated d2: CcD
  )

```

where `b2` is but shouldn’t be deprecated in the yaml, and `c2` is not but should have been.

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 2, 2023, 2:42pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/2 "2023-10-02T14:42:20Z")

</div>

also for `sealed traits` eg in the two commits in  
[Sealedtraits also not working as expected by andersbohn · Pull Request #3 · andersbohn/tapir-redoc-issue · GitHub](https://github.com/andersbohn/tapir-redoc-issue/pull/3) - looks like it works using the concrete case class, but when using the trait as attribute type, the trait become a referenced schema, which IS `deprecated: true` , but this does not show in the UI ?!

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 5, 2023, 12:31pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/3 "2023-10-05T12:31:53Z")

</div>

added a unittest checking the yaml [GitHub - andersbohn/tapir-redoc-issue at sealedtraits](https://github.com/andersbohn/tapir-redoc-issue/tree/sealedtraits).  
so it about tapir scala → openapi (not redoc/swagger)

related to this old discussion: [redoc: Description of properties with a schema reference does not get rendered | gitmotion.com](https://gitmotion.com/redoc/313729186/description-of-properties-with-a-schema-reference-does-not)

which looks like this issue [`@description` behavior is counterintuitive · Issue #1203 · softwaremill/tapir · GitHub](https://github.com/softwaremill/tapir/issues/1203)

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 6, 2023, 10:10am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/4 "2023-10-06T10:10:32Z")

</div>

@andersbohn thanks for the investigation, indeed this seems to be the same issue as the one you linked (1203). It’s due to the fact that we currently assume that there’s a single schema for each type - which, with customisations, might not be the case.

However, with OpenAPI 3.1 now fully supported by Swagger (the dominant “consumer” of the specs generated by tapir), maybe we can fix this.

To make sure we’re on the same page, here’s my simplified example. First, the data classes and the endpoint:

```plaintext
case class Data1(x: String)
case class Data2(@deprecated @description("aaa") a: Data1, @description("bbb") b: Data1)

val e = infallibleEndpoint.get.in(jsonBody[Data2])

```

When interpreted to yaml, we get (somewhat simplified):

```yaml
openapi: 3.1.0
info:
  title: Fruits
  version: '1.0'
paths:
  /:
    get:
      operationId: getRoot
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Data2'
        required: true
      responses:
        '200':
          description: ''
components:
  schemas:
    Data1:
      required:
      - x
      type: object
      properties:
        x:
          type: string
      description: aaa
      deprecated: true
    Data2:
      required:
      - a
      - b
      type: object
      properties:
        a:
          $ref: '#/components/schemas/Data1'
        b:
          $ref: '#/components/schemas/Data1'

```

So the schema for `Data1` now has the properties of the first customisation, while the second is lost. Instead, we’d want to add these customisations to the ref-s:

```yaml
openapi: 3.1.0
info:
  title: Fruits
  version: '1.0'
paths:
  /:
    get:
      operationId: getRoot
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Data2'
        required: true
      responses:
        '200':
          description: ''
components:
  schemas:
    Data1:
      required:
      - x
      type: object
      properties:
        x:
          type: string
    Data2:
      required:
      - a
      - b
      type: object
      properties:
        a:
          $ref: '#/components/schemas/Data1'
          description: aaa
          deprecated: true
        b:
          $ref: '#/components/schemas/Data1'
          description: bbb

```

This renders properly in Swagger UI and redoc according to my tests. There’s also a number of other cases (respons bodies, top-level references etc.) that we’d have to check.

But I think my stratego to implement this would be to see if there are competing schemas for the same type, keep only the common fields, and any extras would get moved to `$ref`. Hopefully this won’t produce some unwanted results 😉

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 6, 2023, 10:16am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/5 "2023-10-06T10:16:30Z")

</div>

As a work-around, you can inline the child schemas (instead of using `$ref`s), if they have [no “name” property](https://tapir.softwaremill.com/en/latest/docs/openapi.html#inlined-and-referenced-schemas).

In case of the example above, this can be done by changing the schema associated to the json’s body:

```plaintext
val e = endpoint.get.in(
  jsonBody[Data2].schema(
    _.modify(_.a)(_.name(None)).modify(_.b)(_.name(None))))

```

This renders:

```yaml
openapi: 3.1.0
info:
  title: Fruits
  version: '1.0'
paths:
  /:
    get:
      operationId: getRoot
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Data2'
        required: true
      responses:
        '200':
          description: ''
        '400':
          description: 'Invalid value for: body'
          content:
            text/plain:
              schema:
                type: string
components:
  schemas:
    Data2:
      required:
      - a
      - b
      type: object
      properties:
        a:
          required:
          - x
          type: object
          properties:
            x:
              type: string
          description: aaa
          deprecated: true
        b:
          required:
          - x
          type: object
          properties:
            x:
              type: string
          description: bbb

```

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 6, 2023, 11:00am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/6 "2023-10-06T11:00:06Z")

</div>

thanks so much @adamw - this morning I finally understood the (somewhat cryptic reference ) in [Generating OpenAPI documentation — tapir 1.x documentation](https://tapir.softwaremill.com/en/latest/docs/openapi.html#inlined-and-referenced-schemas) about this and was experimenting with `schema.name(None)` - (no modify needed, but will try adding it now 🙂 )

I also started drafting a ~rewrite of the question, focusing more on this, including more precise sample on [GitHub - andersbohn/tapir-redoc-issue at simplest\_inlined](https://github.com/andersbohn/tapir-redoc-issue/tree/simplest_inlined) - but maybe l8r.

seems allowing sibling description/deprecation for `$ref`s would be very nice feature. ( I saw somewhere suggested workaround about wrapping $ref and descrtion in some `AllOf`, but cant find that/how-to anywhere in the doc/code)

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 6, 2023, 11:59am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/7 "2023-10-06T11:59:52Z")

</div>

```auto
sealed trait Address - OneAddress, AnotherKindOfAddress, ...

sealed trait Events
  Bitcoin
    SomethingHappened (address: Address, ...)
    SomethingHappenedForOne (address: OneAddress, ...)
  Ethereum
    SomethingVerySpecial (@deprecated oldAddress: AnotherKindOfAddress)
  many more events

```

So inlining the deprecated usage spot is not gonna work, as it is also part of that big coproduct and is used a thousand other places.

IOW seems to me we will require the new feature about annotating $ref-usage

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 6, 2023, 2:50pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/8 "2023-10-06T14:50:56Z")

</div>

Yes, might be so, but that’s a deeper issue than I expected 😉 See [Allow usage-site customisation of referenced schemas by adamw · Pull Request #3228 · softwaremill/tapir · GitHub](https://github.com/softwaremill/tapir/pull/3228) for some early progress.

The additional complexity is due to the fact that there have been some Json Schema / OpenAPI changes since tapir was originally released and we need to catch up.

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 6, 2023, 2:58pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/9 "2023-10-06T14:58:50Z")

</div>

aaw, cool, tnx. Tapir and macros and zio and scala - all so nice when it just works, and then can so quickly get … well hard 🙂

For some reason on our bigger setup the inlined subclasses just seems to disappear. But in the example it just duplicates the whole event-subtree on the affected subclass.

> <https://github.com/andersbohn/tapir-redoc-issue/blob/inside_nested_coproducts_inlined/src/test/resources/docs.yaml>

just to confirm that this is also not usable for our setup.

so clicked vote for the PR 😇

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 10, 2023, 8:30am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/10 "2023-10-10T08:30:00Z")

</div>

Hm I’m not sure what’s the problem with schema inlining, to debug this I’d need a self-contained, minimised, reproducing example - if you could provide one, I’ll take a look 🙂

In the meantime, I’ve release tapir 1.8.0, which should properly represent schemas with independent usage-site modifications - please test and let us know if it works.

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 10, 2023, 5:01pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/11 "2023-10-10T17:01:11Z")

</div>

amazing, so fast, thanks @adamw - I just quickly checked on my sample and it works exactly as it should [Inside nested 1 8 0 by andersbohn · Pull Request #5 · andersbohn/tapir-redoc-issue · GitHub](https://github.com/andersbohn/tapir-redoc-issue/pull/5) 🎉

as for our prod code base, that is a different and likely way longer story, including getting to upgrade to your new release.

oh, not sure if I should click close issue somewhere, but if not clear: as reported I would say it is fixed 👍

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 24, 2023, 3:44pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/12 "2023-10-24T15:44:36Z")

</div>

> [@adamw](#):
>
> self-contained, minimised, reproducing

working on reproducing, but running into another odd NPE for quite small addition of a an extra subclass:  
[wip on multi nested inline coproducts and ref by andersbohn · Pull Request #6 · andersbohn/tapir-redoc-issue · GitHub](https://github.com/andersbohn/tapir-redoc-issue/pull/6#issuecomment-1777514507) 🤔

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 31, 2023, 12:48pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/13 "2023-10-31T12:48:11Z")

</div>

ok, this was just stupid wrong order of implicit schema vals causing the NPEs 🙈

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 31, 2023, 1:13pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/14 "2023-10-31T13:13:40Z")

</div>

Happens every now and then 🙂

So in the end, is there some problem on the tapir side that needs to be still investigated or are we good on this front?

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 31, 2023, 1:35pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/15 "2023-10-31T13:35:15Z")

</div>

@adamw yeah 🙂 tnx - so I just managed to reproduce - of not sure if it is a mistake in my code, but when using `@deprecated option[t]` it is not picked up:

In EventB the @deprecated `deprAName` gets correctly represented in the openapi, but the optional `deprOptionAName` does not.

```auto
  case class EventB(
      aName: AName,
      @Schema.annotations.deprecated
      deprAName: AName,
      @Schema.annotations.deprecated
      deprOptionAName: Option[AName],
      bName: BName
  ) extends Event

```

[sscce\_undepr\_option\_t - Library.scala#L17](https://github.com/andersbohn/tapir-redoc-issue/blob/sscce_undepr_option_t/src/main/scala/dk/andersbohn/tapir/testing/Library.scala#L17)

as seen in the [docs.yaml # 82](https://github.com/andersbohn/tapir-redoc-issue/blob/sscce_undepr_option_t/src/test/resources/docs.yaml#L82) :

```auto
  ...
  deprAName:
    $ref: '#/components/schemas/AName'
    deprecated: true
  deprOptionAName:
    $ref: '#/components/schemas/AName'
  ...

```

(produced with the included testcase `EndpointsSpec`)

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 31, 2023, 3:16pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/16 "2023-10-31T15:16:00Z")

</div>

Ah this seems to be a bug. Can you create another GH issue? 🙂

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [October 31, 2023, 4:27pm UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/17 "2023-10-31T16:27:50Z")

</div>

> [@andersbohn](#):
>
> when using `@deprecated option[t]` it is not picked up:

done [[BUG] Annotations on referenced fields not working for optionals · Issue #3288 · softwaremill/tapir · GitHub](https://github.com/softwaremill/tapir/issues/3288) 👍

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [November 20, 2023, 7:36am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/18 "2023-11-20T07:36:10Z")

</div>

@adamw got notified the bug was fixed, tnx, is it possible for me to check it before it gets released? I can’t find any snapshot release there…

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [November 20, 2023, 8:05am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/19 "2023-11-20T08:05:08Z")

</div>

We don’t publish snapshots, you can build the required modules from source, though

---

<div class="post-metadata">

**Author:** ![andersbohn](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/andersbohn/32/39_2.png) [@andersbohn](https://softwaremill.community/u/andersbohn)\
**Post date:** [November 20, 2023, 8:20am UTC](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289/20 "2023-11-20T08:20:25Z")

</div>

yes, I did try a bit, but that is another big challenge it seems, for another channel 🙂 may have to wait ( I assume it will be for 1.9.x )

[Next page](https://softwaremill.community/t/tapir-redoc-annotations-not-working-as-expected/289.md?page=2)
