Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

OpenApi: optional query and header parameters are documented as nullable

Aperta
#9,461 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Marve10s ci sta già lavorando.

Dal 17/10/2026.

  • #9464 di @Marve10s — aperta

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
57/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
api

Direzione di ricerca

Start in OpenApi.ts at processParameters, the entry point named in the issue, and trace how optional query and header parameter schemas pass through the representation pipeline. Compare those parameter schemas with the body handling described in the issue, then inspect or add focused tests for OpenApi.fromApi query and header output. Done means optional parameters omit JSON null while preserving the documented string forms, with body behavior unchanged.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

What version of Effect is running?

4.0.5. Also seen on 4.0.0. OpenApi.ts on main is the same as in 4.0.5.

What steps can reproduce the bug?

OpenApi.fromApi documents a query parameter declared with Schema.optional as anyOf: [T, null]. A query string has no way to send null, and the server's query decoder doesn't accept one.

import { Schema } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/http-api"

const Query = Schema.Struct({
  limit: Schema.optional(Schema.FiniteFromString),
  cursor: Schema.optional(Schema.NullOr(Schema.String))
})

const Api = HttpApi.make("api").add(
  HttpApiGroup.make("items").add(
    HttpApiEndpoint.get("list", "/items", { query: Query, success: Schema.String })
  )
)

console.log(JSON.stringify(OpenApi.fromApi(Api).paths["/items"].get.parameters, null, 2))

// What the server does with the `null` the document allows
const decodeQuery = Schema.decodeUnknownExit(Schema.toCodecStringTree(Query))
console.log(decodeQuery({ limit: "null" })._tag) // "Failure"
What is the expected behavior?

limit documented as { "type": "string" } with required: false. required: false already says the parameter can be left out, so the undefined that Schema.optional adds has nothing left to describe.

cursor documented with only the string form of its NullOr, anyOf: [{ "type": "string", "enum": ["null"] }, { "type": "string" }], and no JSON null around it.

What do you see instead?
[
  {
    "name": "limit",
    "in": "query",
    "schema": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
    "required": false
  },
  {
    "name": "cursor",
    "in": "query",
    "schema": {
      "anyOf": [
        { "anyOf": [{ "type": "string", "enum": ["null"] }, { "type": "string" }] },
        { "type": "null" }
      ]
    },
    "required": false
  }
]

cursor shows the mismatch most clearly. Its NullOr gets the query codec's representation, the string "null". The undefined from Schema.optional gets the JSON codec's, where Undefined encodes as null. One parameter ends up described by two codecs.

Additional information
  • Headers have the same problem: headers: Schema.Struct({ "x-trace": Schema.optional(Schema.String) }) comes out as anyOf: [{ "type": "string" }, { "type": "null" }].
  • Bodies are fine. A JSON body does decode null to undefined, so T | null is the right description there.
  • Effect's own HttpApiClient is unaffected, since it drops undefined before building the URL. Clients generated from the document are the ones that break. We generate ours with orval, which types limit as string | null and sends ?limit=null when given null. The service then rejects the request, or, for a plain Schema.String, reads "null" as a real value.
  • Switching to Schema.optionalKey fixes the document. It also makes { limit: undefined } fail to encode, so every caller that builds a query from a possibly-undefined value has to leave the key out by hand, which is what Schema.optional exists to avoid.
  • A possible workaround until it's fixed: an OpenApi.Transform that drops the null member from every parameter where required is false.
  • My guess at the cause, from reading the source: processParameters queues parameter schemas as "properties" ops, and those go through the same representation pipeline as bodies, so an optional property's undefined gets the JSON rule.
Lingua principale
TypeScript
Stelle
16.7k
Fork
808
Merge medio
10h 12m
PR unite (30g)
813

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Effect-TS/effect

Tutte le issue di Effect-TS/effect

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.