Skip to content

Angular client: z.void() responseValidator fails with ZodError for 204 No Content responses #3752

@Merururu2975

Description

@Merururu2975

Description

When using the Angular HTTP client plugin with Zod response validation, any endpoint that returns 204 No Content fails with a ZodError. Angular's HttpClient sets response.body to null for empty
responses (standard Angular behavior — HttpResponse.body is typed as T | null). The generated Zod schema z.void() accepts undefined but rejects null.

The issue is in the generated client.gen.ts:

  let bodyResponse = result.response.body  // null for 204                                                                                                                                                 
  if (opts.responseValidator) {                           
    await opts.responseValidator(bodyResponse)  // z.void().parseAsync(null) → ZodError                                                                                                                    
  } 

Current workaround — response interceptor:

client.interceptors.response.use((response) => {                                                                                                                                                         
  if (response.status === 204 && response.body === null) {                                                                                                                                               
    // HttpResponse.clone({ body: undefined }) does NOT work because Angular's clone()                                                                                                                   
    // treats undefined as "keep original value" and the constructor hardcodes                                                                                                                           
    // this.body = init.body !== undefined ? init.body : null
    // so body always ends up as null.  
    // See: https://github.com/angular/angular/blob/2f5ab541eafba72bc0079a8650d0b96b0ddfde2f/packages/common/http/src/response.ts#L319                                                                   
    const cloned = response.clone({ body: undefined });                                                                                                                                                  
    Object.defineProperty(cloned, 'body', { value: undefined });                                                                                                                                         
    return cloned;                                                                                                                                                                                       
  }                                                                                                                                                                                                      
  return response;                                                                                                                                                                                       
});    

Reproducible example or configuration

Any OpenAPI spec with a 204 response:

  paths:
    /example/validation:                                                                                                                                                                                   
      post:
        responses:                                                                                                                                                                                         
          204:                            
            description: Validation succeeded

Generated code:

  // sdk.gen.ts                                                                                                                                                                                            
  responseValidator: async (data) => await zPostExampleValidationResponse.parseAsync(data)           
                                                                      
  // zod.gen.ts                               
  export const zPostExampleValidationResponse = z.void()

Runtime error:

  ZodError: [                                                                                                                                                                                              
    {                                                                                                                                                                                                      
      "expected": "void",                                                                                                                                                                                  
      "code": "invalid_type",             
      "path": [],            
      "message": "Invalid input: expected void, received null"                                                                                                                                             
    }
  ]      

OpenAPI specification (optional)

 openapi: 3.1.0                                                                                                                                                                                           
  paths:        
    /example/validation:                                                                                                                                                                                   
      post:             
        summary: Example validation endpoint
        requestBody:                        
          content:                            
            application/json:             
              schema:        
                type: object                                                                                                                                                                               
        responses:          
          204:                                                                                                                                                                                             
            description: Validation succeeded
          400:                               
            description: Validation failed
            content:                          
              application/json:           
                schema:        
                  type: object                                                                                                                                                                             
                  properties: 
                    title:                                                                                                                                                                                 
                      type: string
                    description:  
                      type: string

System information (optional)

  • @hey-api/openapi-ts: 0.89.2
  • Runtime: Angular 20 with HttpClient
  • Zod: 4.x
  • TypeScript: 5.8
  • Browser: Chrome 133+

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🔥Broken or incorrect behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions