Skip to content

Coercion rules are not working with anyOf #805

@daniele-sarnari-blinkoo

Description

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

5.6.2

Plugin version

6.1.1

Node.js version

v24.10.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

26.0.1

Description

When using AJV with Fastify, type coercion does not seem to work properly when the schema uses an anyOf definition that references another schema.

For example, in the following setup:

const schema = {
  $id: 'LogDetails',
  type: 'object',
  properties: {
    statePrevious: {
      anyOf: [
        // other possible schemas...
        { $ref: 'EntityStateUser#' },
      ],
    },
    stateNext: {
      anyOf: [
        // other possible schemas...
        { $ref: 'EntityStateUser#' },
      ],
    },
  },
  required: ['statePrevious', 'stateNext'],
};

const schemaEntityStateUser = {
  $id: 'EntityStateUser',
  type: 'object',
  properties: {
    id: { type: 'string', format: 'uuid' },
    email: { type: 'string' },
    name: { type: 'string' },
    surname: { type: 'string' },
    enabled: { type: 'boolean' },
    createdAt: { type: 'string' },
    roles: {
      type: 'array',
      items: { $ref: 'Role#' },
    },
  },
  required: [
    'entityType',
    'id',
    'email',
    'name',
    'surname',
    'enabled',
    'createdAt',
    'roles',
  ],
};

fastify.addSchema(schemaEntityStateUser);
fastify.addSchema(schema);

const input = {
  statePrevious: {
    id: 'abc',
    email: 'super secret email',
    name: 'Daniele',
    surname: 'Sarnari',
    enabled: 1, // should be coerced to boolean
    createdAt: '26/09/2022 15:49:02',
    roles: []
  },
  stateNext: {
    id: 'abc',
    email: 'super secret email',
    name: 'Daniele',
    surname: 'Sarnari',
    enabled: 1, // should be coerced to boolean
    createdAt: '26/09/2022 15:49:02',
    roles: []
  },
};

According to the AJV documentation on [type coercion](https://ajv.js.org/coercion.html), the enabled field (a boolean in the schema) should be coerced from 1 to true.

However, when the schema is wrapped inside an anyOf, coercion does not occur, and Fastify returns the following validation error:

The value of 'LogDetails#/properties/statePrevious' does not match schema definition.

(because ajv is not actively coercing the fields in the nested schemas)
If the same setup is changed to use allOf instead of anyOf, coercion works as expected - the numeric value 1 is correctly converted to a boolean true.

Link to code that reproduces the bug

the description should be enough, if not just tell me and i will create a repository

Expected Behavior

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions