Skip to content

multipleOf with decimal (e.g. 0.01) rejects values like 2.34 due to float precision #1105

@Gituar

Description

@Gituar

Description:

This may be considered both a bug and a feature gap:

  • Technically, Ajv (and therefore express-openapi-validator) is behaving correctly per the JSON Schema spec and JavaScript number semantics: 2.34 % 0.01 !== 0 due to IEEE-754 floating-point precision.
  • However, from an OpenAPI user’s perspective, it is very surprising that 2.34 does not satisfy multipleOf: 0.01. Most developers expect decimal values with two digits after the decimal point to be accepted.

Because this leads to unexpected 400 Bad Request errors for otherwise valid-looking inputs, it feels like a bug in express-openapi-validator’s behavior from the user’s point of view, even if it stems from underlying float math.

Error (example):

{
  "name": "Bad Request",
  "status": 400,
  "errors": [
    {
      "path": "/body/price",
      "message": "must be multiple of 0.01",
      "errorCode": "multipleOf.openapi.validation"
    }
  ]
}

Minimal reproducible example:

openapi.yaml:

openapi: 3.0.3
info:
  title: multipleOf repro
  version: 1.0.0
paths:
  /items:
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [price]
              properties:
                price:
                  type: number
                  multipleOf: 0.01
      responses:
        "201":
          description: created

server.js:

import express from 'express';
import { middleware as OpenApiValidator } from 'express-openapi-validator';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const app = express();
app.use(express.json());

app.use(
  OpenApiValidator({
    apiSpec: path.join(__dirname, 'openapi.yaml'),
    validateRequests: true,
    validateResponses: false,
  })
);

app.post('/items', (req, res) => {
  res.status(201).json({ received: req.body });
});

app.use((err, req, res, next) => {
  res.status(err.status || 500).json(err);
});

app.listen(3000, () => {
  console.log('listening at http://localhost:3000');
});

Repro:

curl -X POST http://localhost:3000/items \
  -H "Content-Type: application/json" \
  -d '{"price": 2.34}'

Expected: 201 Created
Actual: 400 Bad Request with multipleOf.openapi.validation

Environment:

express-openapi-validator: 5.5.8

Workarounds:

  • Model the value as a string with a regex for two decimal places, and use SerDes to convert back to number/decimal.
  • Or model currency-like values as integer minor units (e.g., cents) and avoid multipleOf.

Feature Request:

It would be helpful if express-openapi-validator provided a way to handle decimal multipleOf checks safely.

Allow multipleOf on decimal divisors like 0.01 to be checked using decimal arithmetic (configurable).

Example:

OpenApiValidator({
  apiSpec,
  validateRequests: true,
  validateResponses: false,
  decimalSafeMultipleOf: true // new option
})
  • Keeps spec-correct behavior by default.
  • Developers can opt in to “practical decimal” mode.
  • Can be implemented internally by wrapping multipleOf checks with a big-decimal library.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions