Skip to content

Fix NullPointerException in MigrateApiParamSchemaValue for argument-less @ApiParam#77

Open
jsgv wants to merge 1 commit into
openrewrite:mainfrom
jsgv:fix-migrate-apiparam-npe-empty-annotation
Open

Fix NullPointerException in MigrateApiParamSchemaValue for argument-less @ApiParam#77
jsgv wants to merge 1 commit into
openrewrite:mainfrom
jsgv:fix-migrate-apiparam-npe-empty-annotation

Conversation

@jsgv

@jsgv jsgv commented Jun 8, 2026

Copy link
Copy Markdown

What's changed?

MigrateApiParamSchemaValue.visitAnnotation iterates a.getArguments() without a null check. An @ApiParam / @Parameter annotation written without parentheses has null arguments (J.Annotation.getArguments() returns null, not an empty list), so the recipe throws a NullPointerException and aborts the entire run.

This guards against null arguments and returns the annotation unchanged, since there is nothing to migrate when no arguments are present.

What's your motivation?

Running SwaggerToOpenAPI (transitively, via UpgradeSpringBoot_4_0) on a real codebase that uses bare @ApiParam annotations on controller method parameters fails the whole migration:

java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because the return value of "org.openrewrite.java.tree.J$Annotation.getArguments()" is null
  at org.openrewrite.openapi.swagger.MigrateApiParamSchemaValue.visitAnnotation(MigrateApiParamSchemaValue.java:56)

A single argument-less annotation anywhere in the sources aborts the run.

Anything in particular you'd like reviewers to focus on?

The cause is the recipe ordering in MigrateApiParamToParameter: a ChangeType first rewrites @ApiParam to io.swagger.v3.oas.annotations.Parameter, so a parenthesis-less @ApiParam becomes a parenthesis-less @Parameter, which then matches PARAMETER_ANNOTATION_MATCHER and reaches the unchecked getArguments(). Non-@Parameter annotations (e.g. @Override, @RestController) are unaffected because the matcher returns early.

Have you considered any alternatives or workarounds?

Returning early on null arguments is the minimal, semantically-correct fix — a bare @Parameter has no defaultValue/allowableValues to fold into a @Schema, so there is nothing to migrate. getArguments() is @Nullable by design, so callers must null-check.

Any additional context

Added two regression tests covering a bare @ApiParam on a field and on a method parameter (the latter reproduces the original crash); both migrate @ApiParam -> @Parameter without error.

Checklist

  • I've added unit tests to cover both positive and negative cases
  • I've read and applied the recipe conventions and best practices
  • I've used the IntelliJ IDEA auto-formatter on affected files

…ess @ApiParam

A marker @ApiParam / @parameter annotation written without parentheses has
null arguments (J.Annotation.getArguments() returns null, not an empty list).
visitAnnotation iterated the arguments without a null check, throwing a
NullPointerException and aborting the whole recipe run.

Guard against null arguments and return the annotation unchanged, since there
is nothing to migrate when no arguments are present.
@jsgv jsgv force-pushed the fix-migrate-apiparam-npe-empty-annotation branch from ae892a1 to f92bb66 Compare June 9, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

1 participant