growthbook / growthbook/cli

Required path param not enforced on bare no-body invocations

Open
#17 0 comments 0 reactions 0 assignees View on GitHub
bug custom
Dominant language
Go
Stars
1
Forks
0
Avg merge
1d 5h
Merged PRs (30d)
18

Description

## Bug

A required path param is not enforced when a by-id operation is invoked with no flags: bare `growthbook features get` builds `GET /api/v2/features/` with an empty id and returns rc 0 instead of erroring. Providing any other flag restores enforcement (`features get --with-revisions all` → `missing required flag: --id`).

## Root cause (Speakeasy-generated code)

`internal/flagutil/metadata.go` `BuildRequest()` has a body-relaxation heuristic: when `bodyFieldPath == ""` and no flags changed, it calls `relaxRequiredForBodyFields` which sets **all** fields `Required=false` (so a fully-optional body can run argless). GET/DELETE-by-id ops also pass `bodyFieldPath == ""` (they have no body), so the path param's required check is wrongly relaxed on a zero-flag invocation.

Verified against the real call distribution: no-body ops pass `("","")`, whole-struct-body ops pass `("","body")`, sub-field-body ops pass `("Body","body")` — so `bodyFlagName` cleanly separates real-body from no-body ops.

## Stopgap fix (retire when upstream is fixed)

Lives in `.speakeasy/patches/internal/flagutil/metadata.go.patch`: gates the relaxation on `bodyFlagName != ""`, so it only relaxes ops that actually take a body. No-body GET/DELETE-by-id ops now enforce their path param; all-optional list/body ops still run argless.

**To retire:** once Speakeasy scopes the relaxation to actual body operations, remove `metadata.go.patch` and regenerate.

## Refs

- Introduced by #14
- Upstream generator bug — should also be filed to speakeasy-api/speakeasy.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with internal/flagutil/metadata.go and .speakeasy/patches/internal/flagutil/metadata.go.patch, then trace BuildRequest's body-relaxation heuristic. Reproduce with `growthbook features get` and `growthbook features get --with-revisions all`; done means the bare by-id invocation rejects the missing path parameter while fully optional body or list operations remain usable without flags.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.