False positive validation using .spectral ruleset
Given is the following openapi.yml
openapi: 3.0.3
info:
title: Chat Gateway
description: A HTTP Gateway to the grpc chat service.
version: draft
license:
name: UNLICENSED
url: https://www.company.com
contact:
name: Company Inc.
email: [email protected]
url: https://www.company.com
servers:
- url: https://localhost:5000
description: Local Development Server
tags:
- name: authenticate
description: Authentication request
- name: chat
description: Chat service related requests
paths:
/login:
post:
operationId: login
description: Login to the chat server
summary: To use the chat server, you have to login.
security: []
tags:
- authenticate
requestBody:
description: The login request body.
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
example:
name: client.1
responses:
'200':
description: Successful login
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
example:
clientID: 4b84bbfc-e6ee-4e8b-a391-695b07b18416
token: 20ca572a-6797-4c9e-b119-680d780f6738
'400':
$ref: '#/components/responses/400'
'500':
$ref: '#/components/responses/500'
/clients:
get:
operationId: clients
description: Get a list of current clients
summary: This returns a list of current connected clients.
security:
- bearerAuth: []
tags:
- chat
responses:
'200':
description: Successful client list request
content:
application/json:
schema:
$ref: '#/components/schemas/ClientsResponse'
example:
clients:
- name: client.1
clientID: 4b84bbfc-e6ee-4e8b-a391-695b07b18416
'400':
$ref: '#/components/responses/400'
'500':
$ref: '#/components/responses/500'
/messages:
get:
operationId: messages
description: Get a list of received messages
summary: This returns all received but not read messages.
security:
- bearerAuth: [ ]
tags:
- chat
responses:
'200':
description: Successful message list request
content:
application/json:
schema:
$ref: '#/components/schemas/MessagesResponse'
example:
messages:
- message: "Hello from client.1"
clientID: 4b84bbfc-e6ee-4e8b-a391-695b07b18416
'400':
$ref: '#/components/responses/400'
'500':
$ref: '#/components/responses/500'
/send:
post:
operationId: send
description: Send a message
summary: This allows to send a message through the chat server to all connected clients.
security:
- bearerAuth: []
tags:
- chat
requestBody:
description: The message request body.
content:
application/json:
schema:
$ref: '#/components/schemas/SendRequest'
example:
message: "Hello @chat"
responses:
'204':
description: Successful send message
'400':
$ref: '#/components/responses/400'
'500':
$ref: '#/components/responses/500'
components:
securitySchemes:
bearerAuth:
description: Authentication via token. Use the /login request to obtain the token.
type: http
scheme: bearer
schemas:
ErrorCode:
description: The error code.
type: integer
example: 123
ErrorMessage:
description: The error message. Use only for internal evaluation.
type: string
example: validation error
ErrorRelate:
description: Describes a field or parameter this error belongs to. Can be null.
type: string
nullable: true
example: custom.field
ErrorDetail:
type: object
description: contains some detailed error information.
properties:
code:
$ref: '#/components/schemas/ErrorCode'
message:
$ref: '#/components/schemas/ErrorMessage'
relate:
$ref: '#/components/schemas/ErrorRelate'
required:
- code
- message
- relate
example:
code: 123
message: validation error
relate: custom.field
ErrorDetails:
description: A list with error details.
type: array
items:
$ref: '#/components/schemas/ErrorDetail'
example:
- code: 123
message: validation error
relate: custom.field
ErrorResponseDetails:
type: object
description: A detailed error response.
properties:
code:
$ref: '#/components/schemas/ErrorCode'
message:
$ref: '#/components/schemas/ErrorMessage'
error-details:
$ref: '#/components/schemas/ErrorDetails'
required:
- code
- message
- error-details
example:
code: 123
message: validation error
error-details:
- code: 456
message: specific validation error
relate: custom.field
ErrorResponseMinimal:
description: A minimal error response.
type: object
properties:
message:
$ref: '#/components/schemas/ErrorMessage'
required:
- message
example:
message: an error occurred
Token:
description: An auth token
type: string
format: uuid
example: 20ca572a-6797-4c9e-b119-680d780f6738
x-oapi-codegen-extra-tags:
validate: required
ClientName:
description: A client name
type: string
example: client.1
x-oapi-codegen-extra-tags:
validate: required
ClientID:
description: A client id
type: string
format: uuid
example: 4b84bbfc-e6ee-4e8b-a391-695b07b18416
x-oapi-codegen-extra-tags:
validate: required
Client:
description: A client
properties:
name:
$ref: '#/components/schemas/ClientName'
clientID:
$ref: '#/components/schemas/ClientID'
required:
- name
- clientID
Message:
description: A message
properties:
message:
description: The message
type: string
example: "Hello World"
x-oapi-codegen-extra-tags:
validate: required
clientID:
$ref: '#/components/schemas/ClientID'
required:
- message
- clientID
LoginRequest:
description: The login request
properties:
name:
$ref: '#/components/schemas/ClientName'
required:
- name
LoginResponse:
description: The login response
properties:
clientID:
$ref: "#/components/schemas/ClientID"
token:
$ref: "#/components/schemas/Token"
required:
- clientID
- token
ClientsResponse:
description: The clients response
properties:
clients:
description: The clients
type: array
items:
$ref: '#/components/schemas/Client'
example:
- name: client.1
clientID: 4b84bbfc-e6ee-4e8b-a391-695b07b18416
- name: client.2
clientID: 2fb0def5-1c64-42a2-9c98-58c0fa6a3313
x-oapi-codegen-extra-tags:
validate: required
required:
- clients
MessagesResponse:
description: The messages response
properties:
messages:
description: The messages
type: array
items:
$ref: '#/components/schemas/Message'
example:
- message: "Hello from client.1"
clientID: 4b84bbfc-e6ee-4e8b-a391-695b07b18416
- message: "Hello back from client.2"
clientID: 2fb0def5-1c64-42a2-9c98-58c0fa6a3313
x-oapi-codegen-extra-tags:
validate: required
required:
- messages
SendRequest:
description: The send request
properties:
message:
type: string
example: "Hello @chat"
x-oapi-codegen-extra-tags:
validate: required
required:
- message
responses:
'400':
description: An error response.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponseDetails'
examples:
errorResponse:
$ref: '#/components/examples/ErrorResponse'
'500':
description: A bad request response.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponseMinimal'
examples:
basicErrorResponse:
$ref: '#/components/examples/BasicErrorResponse'
examples:
ErrorResponse:
description: An error response example.
value:
code: 123
message: validation error
error-details:
- code: 456
message: specific validation error
relate: custom.field
BasicErrorResponse:
description: A basic error response example.
value:
message: an error occurred
and the .spectral.yml ruleset:
---
extends:
- [spectral:oas, all]
If i lint this, i got the message:
------------------------------------------------
Location | Severity | Message | Rule | Category | Path
openapi.yml:0:0 | warning | 'postResponseSuccess' function has invalid options supplied. Example valid optio... | post-response-success | Operations | $.paths.*.post.responses
This is imho a bug since POST /send contains a valid 204 response.
i tried to reproduce your issue and found that
- if you are leveraging the Doctor online the issue does not appear you have 100% score 🎉
- if you use the command line vacuum generate-ruleset all my-ruleset and then use it , it is also not triggering the issue
the issue is triggerd only when you use the ruleset you mentionned extends: [[spectral:oas, all]]
so there is kind of special case when using this model vs the others even if the rules is 100% the same
notice that the Location 0:0 is suspicious as usually vacuum maintains a precise location for such error, a deep dive is required🐟
I believe this is a duplicate of (or a symptom of) #624.
Hi,
The fix for this was committed: April 25, 2025 (commit 3234b54) Released: v0.16.6 (April 27, 2025) Fixed in: model/utils.go lines 71-73