Skip to content

[BUG] Generated rlang error handling fails for 5xx errors #24796

Description

@jwimberl

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request
Description

With -g r, exceptionPackage: rlang, and returnExceptionOnFailure: true, the
generated API method's 5xx branch calls rlang::abort(message = error_msg, ...).
No variable named error_msg exists anywhere in the generated file; the message
is instead bound as local_var_error_msg. So, when rlang::abort tries to evaluate
the message promise, the call dies with object 'error_msg' not found. This differs
from the useDefaultExceptionHandling case, is also unaffected, since that path calls
stop(local_var_error_msg) correctly.

openapi-generator version

Reproduced using the most recent snapshot,
https://central.sonatype.com/repository/maven-snapshots/org/openapitools/openapi-generator-cli/7.26.0-SNAPSHOT/openapi-generator-cli-7.26.0-20260827.101309-19.jar.

OpenAPI declaration file content or url

Here is a minimal spec which passes openapi-generator validate:

openapi: 3.0.3
info:
  title: Minimal
  version: 1.0.0
paths:
  /ping:
    get:
      operationId: getPing
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pong"
components:
  schemas:
    Pong:
      type: object
      properties:
        message:
          type: string
Generation Details

The settings exceptionPackage: rlang and returnExceptionOnFailure: true are
necessary for this issue, which is specific to the {{#returnExceptionOnFailure}} and
{{#useRlangExceptionHandling}} case.

# config.yaml
packageName: minimalapi
library: httr2
exceptionPackage: rlang
returnExceptionOnFailure: true
Steps to reproduce
  1. Save the spec and config above.
  2. Run the generate command
java -jar openapi-generator-cli-7.26.0-20260827.101309-19.jar \
    generate \
    -i minimal.yaml \
    -g r \
    -c config.yaml \
    -o minimalapi
  1. Inspect out/R/default_api.R. The three abort calls read:
      if (local_var_resp$status_code >= 300 && local_var_resp$status_code <= 399) {
        ...
        rlang::abort(message = local_var_error_msg,      # correct
      } else if (local_var_resp$status_code >= 400 && local_var_resp$status_code <= 499) {
        ...
        rlang::abort(message = local_var_error_msg,      # correct
      } else if (local_var_resp$status_code >= 500 && local_var_resp$status_code <= 599) {
        if (local_var_error_msg == "") {
          local_var_error_msg <- "Api server exception encountered."
        }
        rlang::abort(message = error_msg,                # undefined
  1. Install the generated package in the minimalapi directory and run the following:
library(minimalapi)
api <- DefaultApi$new(ApiClient$new(base_path = "http://localhost"))
local({
  httr2::local_mocked_responses(list(
    httr2::response_json(status_code = 400, body = list(detail = "boom"))
  ))
  api$GetPing()
})

This throws the following error:

Error in self$GetPingWithHttpInfo(data_file = data_file, ..., .parse = .parse) :
  object 'error_msg' not found

This differs from the case where status_code = 400, in which the error is handled
correctly and the corresponding mocked call prints

Error in `self$GetPingWithHttpInfo()` at out/R/default_api.R:75:7:
! {"detail":"boom"}
Run `rlang::last_trace()` to see where the error occurred.
Related issues/PRs

I did not find any, looking for error_msg or rlang::abort as the principal keyword.

Suggest a fix

This can be fixed by a one-line in the R generator's api.mustache, in the
useRlangExceptionHandling block of the 5xx branch (line 657 of the template as
extracted by author template -g r using this maven snapshot):

-        rlang::abort(message = error_msg,
+        rlang::abort(message = local_var_error_msg,

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions