Did you read the migration guide?
Is there an existing issue that is already proposing this?
Potential Commit/PR that introduced the regression
PR #3803 (released in 11.2.7)
Versions
11.2.6 → 11.2.7 (regression still present in 11.3.2)
Describe the regression
PR #3803 (fixes #1639) added a hasExplicitApiResponseDecorator check that suppresses the auto-inferred default response when any decorator whose name matches Api*Response is present. The check doesn't distinguish success (2xx) from error (4xx/5xx) status codes — so a handler decorated with only @ApiUnauthorizedResponse() (or @ApiNotFoundResponse(), @ApiForbiddenResponse(), etc.) no longer gets the auto-inferred 201/200 response in the OpenAPI spec.
The resulting spec lists only the error status code. Downstream client generators (NSwag, openapi-generator, etc.) can't tell that a 2xx is legitimate and treat the real 2xx response as an exception at runtime.
Before 11.2.7, the default 201/200 was always appended, so these handlers produced a complete spec even without an explicit success decorator.
Minimum reproduction code
import { Controller, Post } from '@nestjs/common';
import { ApiUnauthorizedResponse } from '@nestjs/swagger';
@Controller('session')
export class SessionController {
@Post('start')
@ApiUnauthorizedResponse()
startSession(): void {
// defaults to 201 Created at runtime
}
}
Resulting OpenAPI spec:
# 11.2.6 (correct)
/session/start:
post:
responses:
'201': { description: '' } # ← auto-inferred, correct
'401': { description: '' }
# 11.2.7+ (broken)
/session/start:
post:
responses:
'401': { description: '' } # ← 201 silently dropped
Expected behavior
The auto-inferred 2xx response should only be suppressed when at least one success @Api*Response decorator (2xx) is already declared on the handler. Error-only decorators (@ApiUnauthorizedResponse, @ApiNotFoundResponse, @ApiForbiddenResponse, @ApiBadRequestResponse, @ApiConflictResponse, etc.) should not suppress the default.
Other
Real-world impact: in our codebase, a POST /portal-session/start handler with just @ApiUnauthorizedResponse() started throwing ApiException on every successful login after we bumped to 11.2.7, because the generated Angular client had no entry for 201 in its response handler. Downgrading to 11.2.6 confirmed the regression.
Did you read the migration guide?
Is there an existing issue that is already proposing this?
Potential Commit/PR that introduced the regression
PR #3803 (released in 11.2.7)
Versions
11.2.6 → 11.2.7 (regression still present in 11.3.2)
Describe the regression
PR #3803 (fixes #1639) added a
hasExplicitApiResponseDecoratorcheck that suppresses the auto-inferred default response when any decorator whose name matchesApi*Responseis present. The check doesn't distinguish success (2xx) from error (4xx/5xx) status codes — so a handler decorated with only@ApiUnauthorizedResponse()(or@ApiNotFoundResponse(),@ApiForbiddenResponse(), etc.) no longer gets the auto-inferred 201/200 response in the OpenAPI spec.The resulting spec lists only the error status code. Downstream client generators (NSwag, openapi-generator, etc.) can't tell that a 2xx is legitimate and treat the real 2xx response as an exception at runtime.
Before 11.2.7, the default 201/200 was always appended, so these handlers produced a complete spec even without an explicit success decorator.
Minimum reproduction code
Resulting OpenAPI spec:
Expected behavior
The auto-inferred 2xx response should only be suppressed when at least one success
@Api*Responsedecorator (2xx) is already declared on the handler. Error-only decorators (@ApiUnauthorizedResponse,@ApiNotFoundResponse,@ApiForbiddenResponse,@ApiBadRequestResponse,@ApiConflictResponse, etc.) should not suppress the default.Other
Real-world impact: in our codebase, a
POST /portal-session/starthandler with just@ApiUnauthorizedResponse()started throwingApiExceptionon every successful login after we bumped to 11.2.7, because the generated Angular client had no entry for 201 in its response handler. Downgrading to 11.2.6 confirmed the regression.