Skip to content

v1beta3 academy registrationCount is required but generated with omitempty, so a genuine 0 is omitted (and it is float32) #1160

Description

@willcalcote

Summary

registrationCount on the v1beta3 academy curricula response is declared required, then generated with omitempty - so a genuine count of 0 is omitted from the payload entirely, making it indistinguishable from an absent key and putting the response in violation of the schema's own required constraint. It is also typed number, which generates float32 for what is a count of rows.

Evidence

schemas/constructs/v1beta3/academy/api.yml (v1.3.44) declares it required and then authors the tag itself:

    SingleAcademyCurriculaResponse:
      type: object
      allOf:
      - $ref: '#/components/schemas/AcademyCurricula'
      - type: object
        required:
        - registrationCount
        properties:
          registrationCount:
            type: number
            description: Number of registrations associated with this curriculum.
            minimum: 0
            x-oapi-codegen-extra-tags:
              db: registration_count,omitempty
              json: registrationCount,omitempty

Generated Go (models/v1beta3/academy/academy.go:153):

RegistrationCount float32 `db:"registration_count,omitempty" json:"registrationCount,omitempty" yaml:"registrationCount,omitempty"`

So the omitempty is not a generator default that could be argued about - it is written into the schema, on a field the same file marks required, one key above.

Consequences

  1. A zero is unrepresentable. encoding/json drops a 0 under omitempty, so a curriculum with no registrations serializes with no registrationCount at all. A consumer cannot distinguish "measured zero" from "field missing", which is the difference between "nobody enrolled" and "we could not read it".
  2. The response violates its own contract. Any zero-registration curriculum emits a document that fails validation against the required list.
  3. float32 for a row count. type: number generates a float where an integer is meant; minimum: 0 is already declared, so the intent is a non-negative count. Beyond being wrong-typed, float32 loses exactness above 2^24.

Asks

  1. Drop omitempty from the json (and db) extra-tags for a required field, or drop it from required - the two cannot both be right.
  2. Type it as an integer (type: integer, format: int64 or similar) rather than number.

The db tag deserves the same look: omitempty there affects ORM writes, and a zero count that silently does not persist has the same shape of bug on the storage side.

Context

Found while fixing blank date columns in layer5io/meshery-cloud#5985. The instructor console's registration counts have a history with this construct - a stale snake_case read of registration_count after the v1beta3 migration made the overview report "0 registrations" while the learners tab listed hundreds - and this defect makes a real zero look identical to that failure mode, so it is worth closing before the next such bug is diagnosed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions