-
-
Notifications
You must be signed in to change notification settings - Fork 229
Open
Description
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 satisfymultipleOf: 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.
gpor0
Metadata
Metadata
Assignees
Labels
No labels