Skip to content

features create --headless ignores --variables, --variations, and --sdkVisibility #576

Description

@discostu105

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:

  1. There is no dvc variables delete command (variables only has create/get/list/update, and update can't change a variable's type).
  2. 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).

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