atlassian / atlassian/better-ajv-errors

Misleading error when describing deeply nested `anyOf` failure

Open
#153 0 comments 2 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
245
Forks
50
PR merge metrics
No merged PRs in 30d

Description

See minimal, verifiable test case, below.

Briefly, the case below is failing due to the type of the `defaultConfigPath` property being incorrect (`boolean` instead of `string`).

**Expected Result**:

I would expect to see an error message along the lines of "'defaultConfigPath' must be a string, not a boolean" in this case. Or at least an error that summarizes the errors for each of the `anyOf` item failure conditions.

**Actual Result**:

BAE describes the error for the second `anyOf` condition, but not the first:

CleanShot 2022-06-24 at 16 31 06@2x

**Editorial**:

If BAE has to choose just one of many errors passed to it, would it make sense to select error with the deepest `schemaPath`? Or maybe `instancePath`? Intuition tells me that the "deeper" an error is within a data structure, the more likely it is to be something the user can meaningfully act upon.

```jsonc
[
{
// This is the error I would most expect/like to see in this case
instancePath: '/processor/defaultConfigPath',
schemaPath: '#/properties/processor/anyOf/0/properties/defaultConfigPath/type',
keyword: 'type',
params: { type: 'string' },
message: 'must be string'
},
{
// This error, while technically correct, isn't all that relevant since the data doesn't
// match any properties in this sub-schema
instancePath: '/processor',
schemaPath: '#/properties/processor/anyOf/1/required',
keyword: 'required',
params: { missingProperty: 'defaultConfigPackageKey' },
message: "must have required property 'defaultConfigPackageKey'"
},
{
// This error is least likely to be meaningful. And fixing one of the above errors will fix this error.
instancePath: '/processor',
schemaPath: '#/properties/processor/anyOf',
keyword: 'anyOf',
params: {},
message: 'must match a schema in anyOf'
}
]
```

----

## Minimal, stand-alone test case

```js
#!/usr/bin/env node

import Ajv from 'ajv';
import betterAjvErrors from 'better-ajv-errors';

const SCHEMA = {
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
properties: {
processor: {
anyOf: [
{
additionalProperties: false,
type: 'object',
properties: {
defaultConfig: {
type: 'object',
properties: {},
additionalProperties: true
},
defaultConfigPath: {
type: 'string'
}
},
required: ['defaultConfigPath']
},
{
additionalProperties: false,
type: 'object',
properties: {
defaultConfigPackageKey: {
type: 'string'
}
},
required: ['defaultConfigPackageKey']
}
]
}
}
};

const DATA_TO_VALIDATE = `{
"stuff": "... we don't care about",
"processor":{
"defaultConfigPath": true
}
}`;

const validate = new Ajv().compile(SCHEMA)

const data = JSON.parse(DATA_TO_VALIDATE);
if (!validate(data) && validate.errors) {
console.log(
betterAjvErrors(validate.schema, data, validate.errors, { json: DATA_TO_VALIDATE })
);
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Run the standalone JavaScript reproduction with the supplied schema, data, and validation errors, then inspect how better-ajv-errors chooses which nested anyOf failure to display. Compare the output with the requested deeply nested type error and the alternative of summarizing each anyOf failure; done means the misleading result is replaced by an actionable error or clear summary.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
developer-experience, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.