Skip to content

[BUG]: Quicktype not generating the correct descriptions from a CRD, seems to be merging them #2801

Description

@cmwylie19

We use quicktype to generate a json schema from a CRD but are noticing we are getting incorrect descriptions.

Issue Type

The issue is with the output

#!/bin/bash

set -e

curl -sSL https://gist.githubusercontent.com/mjnagel/c4cd6bef02e5c1746a938ec0699f06e5/raw/66ed5fb9fbca7bc36ef29c57ae067154d1567891/crd.yaml -o crd.yaml

yq '.spec.versions[0].schema.openAPIV3Schema' crd.yaml > schema.yaml

yq -o=json schema.yaml > schema.json

quicktype --lang schema \
  --src-lang schema \
  --top-level CustomResource \
  --out crd-schema.json \
  schema.json

If we look at this file, and search the description for network.allow labels description, we see the result should be The labels to apply to the policy.

 > yq ".spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.network.properties.allow.items.properties.labels.description" crd.yaml
The labels to apply to the policy

However, the schema generated has different labels.

> cat crd-schema.json| jq .definitions.Allow.properties.labels.description               
"Labels to match pods in the namespace to apply the policy to. Leave empty to apply to all pods in the namespace\nThe labels to apply to the policy\nDeprecated: use selector\nDeprecated: use remoteSelector\nThe remote pod selector labels to allow traffic to/from\nSpecifies attributes for the client.\nLabels to match pods to automatically protect with authservice. Leave empty to disable authservice protection\nConfiguration options for the mapper.\nAdditional annotations to apply to the generated secret, can be used for pod reloading with a selector\nAdditional labels to apply to the generated secret, can be used for pod reloading\nA template for the generated secret"

Context (Environment, Version, Language)

Input Format:
Output Language:

This affects the CLI and quicktype-core:23.2.6 npm library.

Version:

Description

Input Data

Expected Behaviour / Output

Current Behaviour / Output

Steps to Reproduce

curl -sSL https://gist.githubusercontent.com/mjnagel/c4cd6bef02e5c1746a938ec0699f06e5/raw/66ed5fb9fbca7bc36ef29c57ae067154d1567891/crd.yaml -o crd.yaml

yq '.spec.versions[0].schema.openAPIV3Schema' crd.yaml > schema.yaml

yq -o=json schema.yaml > schema.json

quicktype --lang schema \
  --src-lang schema \
  --top-level CustomResource \
  --out crd-schema.json \
  schema.json

# Get the original description
> yq ".spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.network.properties.allow.items.properties.labels.description" crd.yaml

# Get the generated description
> cat crd-schema.json| jq .definitions.Allow.properties.labels.description  

Possible Solution

Activity

  1. schani commented on Jul 6, 2026

    @schani
    Member

    Triage sweep note (systematic backlog triage, assisted by Claude): confirmed reproducible on current master (v23.3.0, commit 68ecb28), using the CRD gist linked in the issue.

    Root cause: quicktype unifies all structurally identical map types (e.g. every {additionalProperties: string} property across the schema, regardless of which parent object it lives under) into a single graph type. DescriptionTypeAttributeKind.combine in packages/quicktype-core/src/attributes/Description.ts set-unions the description attribute from every occurrence onto that one shared type. Then JSONSchemaRenderer.definitionForObject in packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts (~line 131) inlines that merged type-level description, and only falls back to the correct per-property description when the type-level one is absent — so the merged (and largely irrelevant) description wins for every property that happens to share the same structural shape.

    Verified: definitions.Allow.properties.labels.description in the generated schema contains 11 unrelated descriptions joined by newlines, instead of the expected single string "The labels to apply to the policy".

    Schema validation semantics are unaffected (this is a schema-to-schema pass); only the documentation strings are wrong.

    Assessment:

    • Severity: medium — output is technically valid but the documentation is materially wrong/misleading, which is the entire point of a description field.
    • Fix difficulty: moderate — preferring descriptionForClassProperty over the inlined type-level description in definitionForObject is a small, localized renderer change, but the underlying merged attribute is a direct consequence of type unification, so the fix needs care to avoid regressions in other emit paths that also rely on the merged description.

    Reproduction: uses the CRD linked in the issue (https://gist.githubusercontent.com/mjnagel/c4cd6bef02e5c1746a938ec0699f06e5/raw/66ed5fb9fbca7bc36ef29c57ae067154d1567891/crd.yaml):

    curl -sSL https://gist.githubusercontent.com/mjnagel/c4cd6bef02e5c1746a938ec0699f06e5/raw/66ed5fb9fbca7bc36ef29c57ae067154d1567891/crd.yaml -o crd.yaml
    yq '.spec.versions[0].schema.openAPIV3Schema' crd.yaml | yq -o=json > schema.json
    node dist/index.js --lang schema --src-lang schema --top-level CustomResource --out crd-schema.json schema.json
    jq '.definitions.Allow.properties.labels.description' crd-schema.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions