Skip to content

Generator fabricates list-response JSON wrapper tags from parseSingular(), causing recurring silent-nil-slice bugs #155

Description

@jmsperu

Splitting this out as the systemic root cause behind a recurring class of bugs (#135, #136 / #137, and the four just fixed in #154).

Problem

For List<X>Response structs, generate.go derives the JSON wrapper tag from strings.ToLower(parseSingular(listName)). But the key CloudStack actually returns is set server-side via setObjectName(...), and it is frequently not what parseSingular produces:

  • camelCase: listHypervisorCapabilities → server hypervisorCapabilities, generator hypervisorcapability
  • -xes plural: …Ipv6PrefixesPrefixe (also corrupts the element type name), server guestnetworkipv6prefix
  • hand-chosen keys: listLBHealthCheckPolicies → server healthcheckpolicies (drops the lb, stays plural), generator lbhealthcheckpolicy

When the tag is wrong, json.Unmarshal populates Count but leaves the slice nil — silent data loss — and the generated Get<X>ByID helper then panics on slice[0].

Current mitigation doesn’t scale

generateResponseType already carries a hand-maintained override switch (~30 cases, incl. the metrics ones) that exists precisely to patch this. Each new case is added reactively, only after a user hits a nil slice. #154 adds four more; there are almost certainly others not yet reported.

Note: listApis.json (the generator input) does not expose the list wrapper object name — it carries each item’s response fields and related, but not the setObjectName value — so the correct key can’t simply be read from there.

Proposed directions

  1. Harden parseSingular for the regular English plurals it currently mishandles — -xes/-ses/-ches/-shes → drop es (it already does -ies/-sses). This fixes the Prefixe type-name corruption and several tags for free, shrinking the override set.
  2. Make the override set verifiable instead of reactive: add a CI/test check that asserts each List<X>Response tag against the keys in the test/testdata/*.json fixtures (and/or a captured real response), so drift is caught at build time rather than by users in production.
  3. Optionally, a curated command → objectName override map (cleaner than inline switch cases) seeded from the verified keys.

I verified the #154 keys against the CloudStack server source (setObjectName) and have a 4.22 environment; happy to take on (1) and/or (2) if a maintainer signals a preferred direction.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions