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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions