Skip to content

gateway upsert silently destroys delivery_policy.groups.overrides #393

Description

@leggetter

Summary

Updating a delivery group's rate through gateway destination upsert or gateway connection upsert silently destroys delivery_policy.groups.overrides — per-group overrides the user never mentioned.

Found by exercising a v2.6.0 release-candidate build against the API.

Reproduce

Starting state on a destination:

"delivery_policy": {
  "rate": 200,
  "period": "hour",
  "groups": {
    "key": "body.customer_id",
    "rate": 10,
    "rate_period": "second",
    "overrides": { "cust_1": { "rate": 5, "rate_period": "minute" } }
  }
}

Bump only the group rate:

hookdeck gateway destination upsert my-dest --type HTTP --url https://example.com/x \
  --delivery-group-key body.customer_id --delivery-group-rate 30 --delivery-group-rate-period second

Result: rate: 200 and period: hour are preserved, groups.overrides is gone.

The same happens via gateway connection upsert with the --destination-delivery-group-* forms.

Mechanism

Confirmed by capturing the outgoing request (pointing the CLI at a local server via --api-base). The CLI sends:

{"config":{"delivery_policy":{"groups":{"key":"body.customer_id","rate":30,"rate_period":"second"}},"url":"..."}}

No overrides key — the CLI has no knowledge of the stored value and does not fetch it.

The server then merges delivery_policy one level deep but replaces groups wholesale: that is why sibling rate/period survive (the client omitted them too) while nested overrides does not.

So this is not a client-side bug alone. The CLI omits a field it cannot know; the API's merge treats the two nesting levels differently.

Why it matters

The CLI requires --delivery-group-key and --delivery-group-rate-period to be repeated whenever --delivery-group-rate is given, so "just bump the rate" is necessarily a three-flag command — and that command is exactly the one that wipes overrides. There is no warning and no diff; --dry-run prints only Destination 'x' would be updated.

gateway connection upsert --help states:

Only updates properties that are explicitly provided
Preserves existing properties that aren't specified

Overrides were not specified, and were not preserved.

Options

  1. Client-side fetch-and-merge — read the existing delivery_policy before an upsert that touches groups, and re-send overrides unless the user passed --delivery-group-overrides. Fixes it without API changes; costs a request and introduces a read-modify-write race.
  2. Fix the API merge — make the merge consistent at the groups level. Fixes it for every API consumer, not just the CLI.
  3. Correct the help text — stop promising preservation, and warn when an upsert will replace a groups object that has overrides. Cheapest, but leaves the data loss in place.

Worth a decision involving the API side rather than a unilateral CLI patch, which is why it was left out of #392.

Related


Filed by Claude on Phil's behalf, from release-candidate testing.

Activity

  1. added a commit that references this issue on Sep 14, 2026
    f05ca9e
  2. leggetter commented on Sep 14, 2026

    @leggetter
    CollaboratorAuthor

    Fixed client-side in #392 (f05ca9e) rather than deferred — we're not shipping the release that introduces delivery groups with a known silent data-loss path in them.

    What changed: the stored groups.overrides are carried forward when the caller doesn't supply their own. An explicit --delivery-group-overrides still wins, and '{}' still clears, so deliberately emptying them is unaffected.

    Three paths needed it: destination upsert now fetches the existing destination when a groups object would otherwise go out bare, and both connection upsert paths already hold it, so they cost no extra request.

    Verified against the live API, same destination, A/B:

    • fixed binary → rate bumped to 30, overrides intact
    • pre-fix binary → rate bumped to 45, overrides gone

    Caveat worth recording: this is a read-modify-write and races a concurrent edit of the same destination. That's the same exposure upsert already carries for every other field it preserves, so it's not new, but it is a reason the API-side merge is still the better long-term fix.

    Leaving this open for that — the CLI no longer loses data, but any other API consumer sending a groups object without overrides still will. Suggest retitling to scope it to the API merge, or closing this and opening one against the API if that's tracked elsewhere.

    (Fix and verification by Claude, on Phil's behalf.)

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

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions