Skip to content

[kotlin][jvm-retrofit2] Use @HTTP with hasBody for DELETE operations with a request body - #25469

Open
cpruijsen wants to merge 1 commit into
OpenAPITools:masterfrom
cpruijsen:fix/kotlin-retrofit2-delete-body
Open

cpruijsen wants to merge 1 commit into
OpenAPITools:masterfrom
cpruijsen:fix/kotlin-retrofit2-delete-body

Conversation

@cpruijsen

@cpruijsen cpruijsen commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #25454

With library = jvm-retrofit2, a DELETE operation with a requestBody was generated as @DELETE("path") plus an @Body parameter. Retrofit rejects that on the first call with "Non-body HTTP method cannot contain @Body". A DELETE with a form body fails the same way: "FormUrlEncoded can only be specified on HTTP methods with request body".

The template now emits @HTTP(method = "DELETE", path = "...", hasBody = true) only when the HTTP method does not allow a body (isBodyAllowed is false) and the operation has body or form params (hasBodyOrFormParams). Every other operation keeps the short annotation. The line is shared by the Call, coroutines and Rx variants.

I kept the scope narrow on purpose. #19056 changed every Java retrofit2 operation to @HTTP and was reverted in #19100 because it broke multipart and PUT. With this change, POST, PUT, PATCH and body-less operations generate the same output as before.

Changed files:

  • modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
  • modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenApiTest.java (new test)
  • modules/openapi-generator/src/test/resources/3_0/kotlin/issue25454-delete-with-body.yaml (the issue spec plus a form-body DELETE, a POST with a body and a DELETE without a body)

Testing:

  • The new test fails on master (@HTTP(method = "DELETE", path = "items", hasBody = true) not found) and passes with the change. KotlinClientCodegenApiTest and KotlinClientCodegenModelTest: 101 tests, 0 failures.
  • I regenerated the 14 sample configs that use jvm-retrofit2. No sample file changed, so this PR has no sample updates.
  • I generated a client from the test spec with serializationLibrary=kotlinx_serialization and useCoroutines=true, compiled it with Retrofit 3.0.0, and called each method against OkHttp MockWebServer. On master, deleteItems and deleteItemsForm throw IllegalArgumentException. With the change, the server receives DELETE /items with body {"ids":["a","b"]} and DELETE /items/form with body id=x. The POST and the body-less DELETE behave as before.

The Java retrofit2 template has the same problem. I left it out of this PR.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

cc @karismann @Zomzog @andrewemery @4brunu @yutaka0m @stefankoppier @e5l


Summary by cubic

Fixes DELETE operations with a request body in the Kotlin jvm-retrofit2 client, which previously generated @DELETE annotations that Retrofit rejects at runtime with "Non-body HTTP method cannot contain @Body" (or the equivalent error for form bodies).

The template now emits @HTTP(method = "DELETE", path = "...", hasBody = true) only when the HTTP method does not allow a body and the operation has body or form parameters. All other operations keep their short annotation, so POST, PUT, PATCH, and body-less operations generate the same output as before.

  • Adds a regression test with a JSON-body DELETE, a form-body DELETE, a body-less DELETE, and a POST to verify the annotations.

Written for commit a3d4c8c. Summary will update on new commits.

View guided diff

…with a request body

Retrofit rejects @Body, @FormUrlEncoded and @multipart on @delete, so a
DELETE operation with a requestBody failed on its first call. Emit
@http(method, path, hasBody = true) only when the method does not allow a
body and the operation has body or form params. Other operations keep the
short annotation, so existing output does not change.

Fixes OpenAPITools#25454

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

View guided diff | Re-trigger cubic

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][KOTLIN] jvm-retrofit2: DELETE with requestBody fails with "Non-body HTTP method cannot contain @Body"

1 participant