Skip to content

Reported Error location does not point at correct node for Parameters #1241

@jeremyfiel

Description

@jeremyfiel

Describe the bug

When an error is produced for a required parameter in the uri, the error location points at the component schema rather than the actual error location in the parameters collection, this makes it difficult to trace which line has the actual error. In this example, the $ref on line 89 should be indicated.

To Reproduce
Steps to reproduce the behavior:

  1. Given this redocly.yaml file
extends:
  - recommended
  1. And this OpenAPI file(s)
{
    "openapi": "3.1.0",
    "info": {
        "title": "freeCodeCamp Classroom",
        "version": "0.0.1",
        "contact": {
            "name": "Classroom Team",
            "email": ""
        },
        "license": {
            "name": "",
            "url": ""
        }
    },
    "servers": [
        {
            "url": "https://api.freecodecamp.org"
        }
    ],
    "security": [],
    "tags": [
        {
            "name": "Classroom user data",
            "description": ""
        }
    ],
    "paths": {
        "/classroom/userData": {
            "get": {
                "summary": "",
                "description": "",
                "operationId": "getUserData",
                "tags": [
                    "Classroom user data"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/header_accept"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/userData"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/400"
                    },
                    "401": {
                        "$ref": "#/components/responses/401"
                    },
                    "403": {
                        "$ref": "#/components/responses/403"
                    },
                    "404": {
                        "$ref": "#/components/responses/404"
                    },
                    "500": {
                        "$ref": "#/components/responses/500"
                    },
                    "503": {
                        "$ref": "#/components/responses/503"
                    }
                }
            },
            "post": {
                "summary": "",
                "description": "",
                "operationId": "queryUserData",
                "tags": [
                    "Classroom user data"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/header_contentType"
                    },
                    {
                        "$ref": "#/components/parameters/path_userId"
                    }
                ],
                "requestBody": {
                    "$ref": "#/components/requestBodies/userDataRequest"
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/userData"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/400"
                    },
                    "401": {
                        "$ref": "#/components/responses/401"
                    },
                    "403": {
                        "$ref": "#/components/responses/403"
                    },
                    "404": {
                        "$ref": "#/components/responses/404"
                    },
                    "500": {
                        "$ref": "#/components/responses/500"
                    },
                    "503": {
                        "$ref": "#/components/responses/503"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "problem_json_error": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string"
                    },
                    "status": {
                        "type": "number",
                        "minimum": 200,
                        "maximum": 511
                    },
                    "title": {
                        "type": "string"
                    },
                    "detail": {
                        "type": "string"
                    },
                    "instance": {
                        "type": "string",
                        "format": "uri-reference"
                    }
                }
            },
            "userData": {
                "$id": "https://api.freecodecamp.org/classroom/userData",
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "description": "list of students",
                "type": "array",
                "uniqueItems": true,
                "items": {
                    "type": "object",
                    "properties": {
                        "user": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string"
                                },
                                "email": {
                                    "description": "student identifier",
                                    "type": "string",
                                    "format": "email"
                                }
                            }
                        },
                        "certifications": {
                            "description": "name of the certification (\"2022/responsive-web-design\")",
                            "type": "array",
                            "uniqueItems": true,
                            "minItems": 1,
                            "items": {
                                "description": "name of the certification block",
                                "type": "object",
                                "propertyNames": {
                                    "pattern": "^[A-Za-z0-9][\/A-Za-z0-9-]*[A-Za-z]$"
                                },
                                "additionalProperties": {
                                    "type": "object",
                                    "unevaluatedProperties": false,
                                    "properties": {
                                        "blocks": {
                                            "description": "List of the challenges/blocks inside of a certification",
                                            "type": "array",
                                            "uniqueItems": true,
                                            "items": {
                                                "type": "object",
                                                "minProperties": 1,
                                                "additionalProperties": {
                                                    "description": "name of the block (learn-css-...)",
                                                    "type": "object",
                                                    "properties": {
                                                        "completedChallenges": {
                                                            "type": "array",
                                                            "description": "list of challenges completed by the student inside of this block",
                                                            "uniqueItems": true,
                                                            "items": {
                                                                "$ref": "#/$defs/Challenge"
                                                            }
                                                        }
                                                    },
                                                    "required": [
                                                        "completedChallenges"
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "required": [
                        "user",
                        "certifications"
                    ]
                },
                "$defs": {
                    "Challenge": {
                        "description": "A representation of an individual challenge",
                        "type": "object",
                        "unevaluatedProperties": false,
                        "required": [
                            "id",
                            "challengeName",
                            "completedDate"
                        ],
                        "properties": {
                            "id": {
                                "description": "A unique identifier of a completed course",
                                "type": "string",
                                "minLength": 1
                            },
                            "challengeName": {
                                "type": "string"
                            },
                            "completedDate": {
                                "description": "A Unix timestamp representation",
                                "type": "integer"
                            },
                            "files": {
                                "description": "A list of files pertaining to the challenge",
                                "type": "array",
                                "uniqueItems": true,
                                "items": {
                                    "$ref": "#/$defs/File"
                                }
                            }
                        }
                    },
                    "File": {
                        "description": "A representation of a file",
                        "type": "string",
                        "format": "binary"
                    }
                }
            }
        },
        "parameters": {
            "header_accept": {
                "name": "accept",
                "description": "",
                "in": "header",
                "schema": {
                    "type": "string"
                },
                "examples": {
                    "accept_header": {
                        "summary": "A standard header indicating the accepted media type",
                        "value": "application/json"
                    }
                }
            },
            "header_contentType": {
                "name": "content-type",
                "description": "",
                "in": "header",
                "schema": {
                    "type": "string"
                },
                "examples": {
                    "content-type": {
                        "summary": "A standard header indicating the content media type",
                        "value": "application/json"
                    }
                }
            },
            "path_userId": {
                "name": "user-id",
                "description": "",
                "in": "path",
                "schema": {
                    "type": "string"
                },
                "required": true
            }
        },
        "requestBodies": {
            "userDataRequest": {
                "description": "",
                "content": {
                    "application/json": {
                        "schema": {
                            "$schema": "https://json-schema.org/draft/2020-12/schema",
                            "title": "UserDataRequest",
                            "description": "Queries a collection of users and certifications",
                            "type": "object",
                            "unevaluatedProperties": false,
                            "properties": {
                                "users": {
                                    "type": "array",
                                    "uniqueItems": true,
                                    "minItems": 1,
                                    "prefixItems": [
                                        {
                                            "type": "object",
                                            "unevaluatedProperties": false,
                                            "properties": {
                                                "id": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "id"
                                            ]
                                        }
                                    ],
                                    "items": {
                                        "description": "name of the certification block",
                                        "type": "string",
                                        "pattern": "^[A-Za-z0-9][\/A-Za-z0-9-]*[A-Za-z]$"
                                    }
                                }
                            },
                            "required": [
                                "users"
                            ]
                        }
                    }
                },
                "required": true
            }
        },
        "responses": {
            "400": {
                "description": "Bad Request",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/problem_json_error"
                        }
                    }
                }
            },
            "401": {
                "description": "Unauthorized",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/problem_json_error"
                        }
                    }
                }
            },
            "403": {
                "description": "Forbidden",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/problem_json_error"
                        }
                    }
                }
            },
            "404": {
                "description": "Not Found",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/problem_json_error"
                        }
                    }
                }
            },
            "500": {
                "description": "Internal Server Error",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/problem_json_error"
                        }
                    }
                }
            },
            "503": {
                "description": "Service Unavailable",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/problem_json_error"
                        }
                    }
                }
            }
        }
    }
}
  1. Run this command with these arguments...
    redocly lint --config redocly.yaml fcc-classroom-userdata-openapi.json

  2. See error

  302:25  error    path-parameters-defined  Path parameter `user-id` is not used in the path `/classroom/userData`.

Expected behavior

The error location line number shall be the correct node where the error occurs, not the referenced location

Redocly Version(s)

redocly --version
1.0.2

Node.js Version(s)

node v14.18.1 (npm v6.14.15)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions