Summary
In headless mode, dvc features create silently ignores the --variables, --variations, and --sdkVisibility flags. Regardless of what is passed, it scaffolds the feature with a single Boolean variable keyed to the feature, default variation-on/variation-off variations (true/false), and sdkVisibility set to all-true.
The net effect is that it's impossible to create a String/Number/JSON variable, custom variations, or restricted SDK visibility through features create in headless/CI usage.
Environment
@devcycle/cli 6.3.2 (darwin-arm64, bundled node-v26.4.0)
- macOS 26.5
Repro
dvc features create --headless \
--key my-feature \
--name "My Feature" \
--variables '[{"key":"my-mode","name":"my-mode","type":"String","validationSchema":{"schemaType":"enum","enumValues":["a","b"],"exampleValue":"a"}}]' \
--variations '[{"key":"variation-a","name":"A","variables":{"my-mode":"a"}},{"key":"variation-b","name":"B","variables":{"my-mode":"b"}}]' \
--sdkVisibility '{"mobile":false,"client":false,"server":true}'
Expected
A feature with:
- a String variable
my-mode (enum a/b),
- variations
A / B mapping my-mode to a / b,
sdkVisibility = { mobile: false, client: false, server: true }.
Actual
A feature with:
- a Boolean variable named after the feature key (
my-feature),
- variations
variation-on (true) / variation-off (false),
sdkVisibility = { mobile: true, client: true, server: true }.
All three provided flags are dropped.
Notes / diagnosis
- The provided JSON is valid against the CLI's own zod schemas. Requiring the bundled
dist/api/zodSchemas.js and calling CreateFeatureDto.parse({ key, name, variables, variations, sdkVisibility, headless: true }) succeeds and retains all fields — so this is not a client-side validation rejection; the values simply aren't honored by the create.
- Creating an equivalent feature directly via the Management API (
POST /v2/projects/:project/features) with only key/name returns an empty feature (no variables, no variations) — i.e. the Boolean scaffold appears to be added by the CLI, not the API. This suggests the headless path isn't forwarding the parsed --variables/--variations/--sdkVisibility into the create request.
Related gaps that make recovery hard
Once the wrong (Boolean) variable is created, it can't be fixed or removed through the CLI:
- There is no
dvc variables delete command (variables only has create/get/list/update, and update can't change a variable's type).
dvc features delete <key> does not cascade-delete the feature's variables. After deleting the feature, dvc variables get --keys <key> still returns the (now orphaned) variable, which keeps occupying the variable key.
Combined, a variable created by the buggy scaffold cannot be deleted via the CLI at all — I had to fall back to the Management API (DELETE /v1/projects/:project/variables/:key) to clean up and to create the String variable I actually wanted.
Suggested fixes
- In headless mode, forward the parsed
--variables, --variations, and --sdkVisibility into the createFeature request (and don't inject a default Boolean variable when variables are supplied).
- Add a
dvc variables delete command, and/or make features delete cascade to its variables (or document the orphaning behavior and offer a --cascade flag).
Summary
In headless mode,
dvc features createsilently ignores the--variables,--variations, and--sdkVisibilityflags. Regardless of what is passed, it scaffolds the feature with a single Boolean variable keyed to the feature, defaultvariation-on/variation-offvariations (true/false), andsdkVisibilityset to all-true.The net effect is that it's impossible to create a
String/Number/JSONvariable, custom variations, or restricted SDK visibility throughfeatures createin headless/CI usage.Environment
@devcycle/cli6.3.2 (darwin-arm64, bundlednode-v26.4.0)Repro
Expected
A feature with:
my-mode(enuma/b),A/Bmappingmy-modetoa/b,sdkVisibility={ mobile: false, client: false, server: true }.Actual
A feature with:
my-feature),variation-on(true) /variation-off(false),sdkVisibility={ mobile: true, client: true, server: true }.All three provided flags are dropped.
Notes / diagnosis
dist/api/zodSchemas.jsand callingCreateFeatureDto.parse({ key, name, variables, variations, sdkVisibility, headless: true })succeeds and retains all fields — so this is not a client-side validation rejection; the values simply aren't honored by the create.POST /v2/projects/:project/features) with onlykey/namereturns an empty feature (no variables, no variations) — i.e. the Boolean scaffold appears to be added by the CLI, not the API. This suggests the headless path isn't forwarding the parsed--variables/--variations/--sdkVisibilityinto the create request.Related gaps that make recovery hard
Once the wrong (Boolean) variable is created, it can't be fixed or removed through the CLI:
dvc variables deletecommand (variablesonly hascreate/get/list/update, andupdatecan't change a variable'stype).dvc features delete <key>does not cascade-delete the feature's variables. After deleting the feature,dvc variables get --keys <key>still returns the (now orphaned) variable, which keeps occupying the variable key.Combined, a variable created by the buggy scaffold cannot be deleted via the CLI at all — I had to fall back to the Management API (
DELETE /v1/projects/:project/variables/:key) to clean up and to create the String variable I actually wanted.Suggested fixes
--variables,--variations, and--sdkVisibilityinto thecreateFeaturerequest (and don't inject a default Boolean variable when variables are supplied).dvc variables deletecommand, and/or makefeatures deletecascade to its variables (or document the orphaning behavior and offer a--cascadeflag).