REST Lens
← Back to All Rules
Rule 35

Code 204 Empty

Category: Response Design

Description

204 No Content responses must not include a response body, and other 2XX success responses should always include a response body unless using 204.

What It Checks

This rule validates proper usage of HTTP 204 status codes and response bodies across all successful (2XX) responses. It checks:

  • 204 No Content responses must have no response body (content should be empty or absent)
  • Other 2XX status codes (200, 201, 202, etc.) must include a response body
  • Response bodies are not semantically empty (e.g., empty schemas or blank objects)
  • Excludes generic "2XX" response definitions (cannot be validated without specific code)

Why It Matters

Proper handling of 204 status codes and response bodies is crucial for HTTP compliance and client expectations:

  • HTTP specification compliance: RFC 7231 explicitly states that 204 responses MUST NOT contain a message body
  • Client efficiency: 204 responses save bandwidth by not transmitting unnecessary empty response bodies
  • Clear semantics: Distinguishes between "no content to return" (204) vs "successful operation with data" (200, 201, etc.)
  • Cache behavior: Proxies and caches handle 204 responses differently than 200 responses
  • Framework compatibility: Many HTTP clients and frameworks expect 204 to have no body and may error if one is present

Examples

Good ✅

paths:
  /users/{userId}:
    delete:
      summary: Delete a user
      responses:
        '204':
          description: User successfully deleted
          # No content specified - correct for 204

    patch:
      summary: Update a user
      responses:
        '200':
          description: User updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

  /posts/{postId}/like:
    post:
      summary: Like a post
      responses:
        '204':
          description: Post liked successfully
          # No content - appropriate for state change with no data to return

  /resources:
    post:
      summary: Create a resource
      responses:
        '201':
          description: Resource created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Resource'

Bad ❌

paths:
  /users/{userId}:
    delete:
      summary: Delete a user
      responses:
        '204':
          description: User deleted
          content:  # ❌ 204 should not have content
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string

    patch:
      summary: Update a user
      responses:
        '200':
          description: User updated
          # ❌ 200 response should have content but none specified

  /posts:
    get:
      summary: List posts
      responses:
        '200':
          description: Posts retrieved
          content:
            application/json:
              schema:
                type: object  # ❌ Semantically empty - no properties defined

  /settings:
    put:
      summary: Update settings
      responses:
        '202':
          description: Settings update queued
          # ❌ 202 should include content (e.g., job ID or status)

Exceptions

The rule allows these cases:

  1. Generic 2XX responses: Definitions using "2XX" (cannot validate without specific status code)
  2. Operations with only generic 2XX: If no specific 2XX codes are defined, no violation is raised

Configuration

This rule has no configuration options. It is either enabled or disabled.

How to Fix

Fix 1: Remove body from 204 responses

# Before
responses:
  '204':
    description: Deleted successfully
    content:
      application/json:
        schema:
          type: object
          properties:
            message:
              type: string

# After
responses:
  '204':
    description: Deleted successfully
    # No content specified

Fix 2: Use 200 instead of 204 when returning data

# Before (incorrect use of 204 with body)
responses:
  '204':
    description: Updated
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/User'

# After
responses:
  '200':
    description: User updated successfully
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/User'

Fix 3: Add response body to non-204 success responses

# Before
responses:
  '200':
    description: Operation successful
    # Missing content

# After
responses:
  '200':
    description: Operation successful
    content:
      application/json:
        schema:
          type: object
          properties:
            status:
              type: string
              example: success
            data:
              $ref: '#/components/schemas/Result'

Fix 4: Define complete schemas (avoid semantically empty responses)

# Before
responses:
  '200':
    description: Success
    content:
      application/json:
        schema:
          type: object  # Empty object with no properties

# After
responses:
  '200':
    description: Success
    content:
      application/json:
        schema:
          type: object
          properties:
            id:
              type: string
            status:
              type: string
            createdAt:
              type: string
              format: date-time

When to Use 204 vs 200

Use 204 No Content when:

  • DELETE operations where no data needs to be returned
  • PUT/PATCH operations where the client already has all the updated data
  • POST operations for actions that don't create resources (e.g., liking a post)
  • Any operation where success is confirmed but no response body is needed

Use 200 OK when:

  • GET operations (always return data)
  • PUT/PATCH operations returning the updated resource
  • POST operations returning the created resource
  • Any operation where response data provides value to the client

Use 201 Created when:

  • POST operations creating new resources (should include the created resource in response body)

Use 202 Accepted when:

  • Async operations (should include job ID or status tracking information)

Related Rules

  • Rule 34: Code 201 Create - Ensures creation operations return 201 status code
  • Rule 53: Create Update Return - Validates proper response codes for creation and update operations