Problem
Schema annotations like examples and default are typed parametrically against the schema's decoded Type (Annotations.Documentation<T> uses ReadonlyArray<T> / T). So on a Schema.BigInt, Schema.Symbol, or Schema.UndefinedOr(...) schema, annotating with 123n, Symbol.for("a"), or undefined is perfectly type-correct — but these values are not JSON-representable, and they poison JSON Schema / OpenAPI generation with no warning at the annotation site.
Verified against effect@4.0.0-beta.101 with TypeScript 7.0.2 --strict: tsc is completely silent, yet Schema.toJsonSchemaDocument emits a document containing raw bigint values, so JSON.stringify of the generated "JSON Schema" throws Do not know how to serialize a BigInt. The Effect team has already been bitten by this class of bug and now filters such values at generation time:
38abd6799 — filter non-JSON values from schema examples and defaults, closes #5884 (#5888)
44e0b0444 — JSONSchema: add missing options for target JSON Schema version, closes #5883 (#5885)
Whether the outcome is invalid output (as observed on this beta) or silent filtering (post-fix behavior), the user's carefully written examples either break serialization or just vanish from the generated OpenAPI document. The statically visible cases (bigint, symbol, undefined, function types) are cheap to catch where the annotation is written.
Reproduction
import { Schema } from "effect"
const Balance = Schema.BigInt.annotate({
examples: [123n], // not JSON-representable
default: 0n
})
const WithUndefined = Schema.UndefinedOr(Schema.Number).annotate({
examples: [undefined, 1]
})
const WithSymbol = Schema.Symbol.annotate({
examples: [Symbol.for("a")],
default: Symbol.for("b")
})
// Same footgun via annotateKey on a struct property
const Account = Schema.Struct({
balance: Schema.BigInt.annotateKey({ examples: [42n], default: 0n })
})
const doc = Schema.toJsonSchemaDocument(Balance)
JSON.stringify(doc)
tsc --strict reports nothing (exit 0). At runtime, toJsonSchemaDocument passes the bigints straight through into the draft-2020-12 document, and JSON.stringify(doc) throws TypeError: Do not know how to serialize a BigInt — the generated "JSON Schema" is not serializable, with no warning at the annotation site.
Proposed rule behavior
- When: at
.annotate(...) / .annotateKey(...) calls on Schema-typed receivers (and the curried Schema.annotate / Schema.annotateKey / Schema.annotateEncoded pipeables), when the annotation object has an examples or default property. Note: this targets the v4 API surface — v3's .annotations({...}) spelling does not exist in v4.
- Check: for
default and each element of examples, get the checker type of the supplied value expression; report when it contains bigint, symbol, undefined, or a callable type (union members included).
- Report on: the offending value expression (or the
examples/default property when the value is not syntactically decomposable).
- Message:
`examples`/`default` value of type 'bigint' is not a JSON value — it will be silently omitted from (or corrupt) the generated JSON Schema. Annotate the encoded side or provide a `jsonSchema` override.
- Code fix (suggestion): none automatic; optionally offer to move the annotation to
annotateEncoded when the encoded type is JSON-representable.
- Must NOT flag:
- schemas that override the
jsonSchema annotation (the user has taken control of generation);
- annotation values whose types are JSON-representable (string, number, boolean, null, plain arrays/objects of those);
- other annotation keys (
title, description, identifier, ...);
- values typed
any/unknown (avoid noise; only statically certain non-JSON kinds).
- Relation to existing rules: complements
preferSchemaOverJson and the schema* family (schemaNumber, schemaStructWithTag, ...) which target schema construction; none of them inspect annotation values, so there is no overlap.
Proposed rule name
schemaNonJsonAnnotation — matches the schema* prefix convention and names the defect (non-JSON annotation value) concisely. Recommended.
schemaNonJsonExamples — more specific, but understates that default is covered too.
nonJsonValueInSchemaAnnotation — most descriptive, but longer than the surrounding rule set's style.
Problem
Schema annotations like
examplesanddefaultare typed parametrically against the schema's decodedType(Annotations.Documentation<T>usesReadonlyArray<T>/T). So on aSchema.BigInt,Schema.Symbol, orSchema.UndefinedOr(...)schema, annotating with123n,Symbol.for("a"), orundefinedis perfectly type-correct — but these values are not JSON-representable, and they poison JSON Schema / OpenAPI generation with no warning at the annotation site.Verified against
effect@4.0.0-beta.101with TypeScript 7.0.2--strict:tscis completely silent, yetSchema.toJsonSchemaDocumentemits a document containing rawbigintvalues, soJSON.stringifyof the generated "JSON Schema" throwsDo not know how to serialize a BigInt. The Effect team has already been bitten by this class of bug and now filters such values at generation time:38abd6799— filter non-JSON values from schema examples and defaults, closes #5884 (#5888)44e0b0444— JSONSchema: add missing options for target JSON Schema version, closes #5883 (#5885)Whether the outcome is invalid output (as observed on this beta) or silent filtering (post-fix behavior), the user's carefully written examples either break serialization or just vanish from the generated OpenAPI document. The statically visible cases (
bigint,symbol,undefined, function types) are cheap to catch where the annotation is written.Reproduction
tsc --strictreports nothing (exit 0). At runtime,toJsonSchemaDocumentpasses the bigints straight through into the draft-2020-12 document, andJSON.stringify(doc)throwsTypeError: Do not know how to serialize a BigInt— the generated "JSON Schema" is not serializable, with no warning at the annotation site.Proposed rule behavior
.annotate(...)/.annotateKey(...)calls on Schema-typed receivers (and the curriedSchema.annotate/Schema.annotateKey/Schema.annotateEncodedpipeables), when the annotation object has anexamplesordefaultproperty. Note: this targets the v4 API surface — v3's.annotations({...})spelling does not exist in v4.defaultand each element ofexamples, get the checker type of the supplied value expression; report when it containsbigint,symbol,undefined, or a callable type (union members included).examples/defaultproperty when the value is not syntactically decomposable).`examples`/`default` value of type 'bigint' is not a JSON value — it will be silently omitted from (or corrupt) the generated JSON Schema. Annotate the encoded side or provide a `jsonSchema` override.annotateEncodedwhen the encoded type is JSON-representable.jsonSchemaannotation (the user has taken control of generation);title,description,identifier, ...);any/unknown(avoid noise; only statically certain non-JSON kinds).preferSchemaOverJsonand theschema*family (schemaNumber,schemaStructWithTag, ...) which target schema construction; none of them inspect annotation values, so there is no overlap.Proposed rule name
schemaNonJsonAnnotation— matches theschema*prefix convention and names the defect (non-JSON annotation value) concisely. Recommended.schemaNonJsonExamples— more specific, but understates thatdefaultis covered too.nonJsonValueInSchemaAnnotation— most descriptive, but longer than the surrounding rule set's style.