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
- 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".
- The response violates its own contract. Any zero-registration curriculum emits a document that fails validation against the
required list.
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
- Drop
omitempty from the json (and db) extra-tags for a required field, or drop it from required - the two cannot both be right.
- 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.
Summary
registrationCounton the v1beta3 academy curricula response is declaredrequired, then generated withomitempty- 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 ownrequiredconstraint. It is also typednumber, which generatesfloat32for 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:Generated Go (
models/v1beta3/academy/academy.go:153):So the
omitemptyis 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
encoding/jsondrops a0underomitempty, so a curriculum with no registrations serializes with noregistrationCountat all. A consumer cannot distinguish "measured zero" from "field missing", which is the difference between "nobody enrolled" and "we could not read it".requiredlist.float32for a row count.type: numbergenerates a float where an integer is meant;minimum: 0is already declared, so the intent is a non-negative count. Beyond being wrong-typed, float32 loses exactness above 2^24.Asks
omitemptyfrom thejson(anddb) extra-tags for a required field, or drop it fromrequired- the two cannot both be right.type: integer,format: int64or similar) rather thannumber.The
dbtag deserves the same look:omitemptythere 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_countafter 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.