larksuite/cli · error

ValueSources must include flag

Error message

ValueSources must include flag

What it means

When ValueSources is non-empty, the flag source is mandatory: multi-source inputs are defined as 'flag first, optionally supplemented by file/stdin'. validateInputCLI rejects a list like [file] or [stdin] alone because a field whose value never comes from the command line flag breaks the CLI contract for primary inputs.

Source

Thrown at shortcuts/common/typed_compile_args.go:293

	}
	if field.defaultValue.Set {
		if err := valueAssignableTo(field.defaultValue.Value, field.valueType); err != nil {
			return fmt.Errorf("default: %w", err)
		}
	}
	seenSources := make(map[typedValueSource]struct{})
	for _, source := range field.cli.ValueSources {
		if source != typedSourceFlag && source != typedSourceFile && source != typedSourceStdin {
			return fmt.Errorf("unknown value source %q", source)
		}
		if _, duplicate := seenSources[source]; duplicate {
			return fmt.Errorf("duplicate value source %q", source)
		}
		seenSources[source] = struct{}{}
	}
	if len(field.cli.ValueSources) > 0 {
		if _, ok := seenSources[typedSourceFlag]; !ok {
			return fmt.Errorf("ValueSources must include flag")
		}
		if (len(seenSources) > 1) && indirectKind(field.valueType) != reflect.String && field.cli.Encoding != typedEncodingJSON {
			return fmt.Errorf("file/stdin sources require string input or encoding=json")
		}
	}
	kind := indirectKind(field.valueType)
	if kind == reflect.Slice || kind == reflect.Array || kind == reflect.Struct || kind == reflect.Map || kind == reflect.Interface {
		if field.cli.Encoding == "" {
			return fmt.Errorf("%s input must explicitly declare CLI encoding", kind)
		}
	}
	switch field.cli.Encoding {
	case "":
		if kind == reflect.Slice || kind == reflect.Array || kind == reflect.Struct || kind == reflect.Map || kind == reflect.Interface {
			return fmt.Errorf("complex input requires encoding")
		}
	case typedEncodingRepeated:
		if kind != reflect.Slice && kind != reflect.Array {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Add "flag" as the first entry of ValueSources
  2. If the field must not be a CLI flag, do not use ValueSources - hide the flag (CLI.Hidden) instead
  3. Remove ValueSources entirely to fall back to the default flag-only behavior

Example fix

// before
ValueSources: []string{"file", "stdin"}
// after
ValueSources: []string{"flag", "file", "stdin"}
Defensive patterns

Strategy: validation

Validate before calling

func hasFlagSource(srcs []string) bool {
	for _, s := range srcs {
		if s == "flag" {
			return true
		}
	}
	return false
}
// require len(srcs) == 0 || hasFlagSource(srcs)

Try / catch

if err := compileInput(...); err != nil {
	if strings.Contains(err.Error(), "must include flag") {
		// prepend "flag" to ValueSources
	}
	return err
}

Prevention

When it happens

Trigger: Declaring ValueSources without "flag", e.g. ValueSources: []string{"file"} or []string{"file","stdin"}, intending to read the value only from a file or stdin. Raised by compileInput during shortcut compilation.

Common situations: Assuming a field can be file-only or stdin-only; building a 'silent' input that is never shown as a flag; misunderstanding that ValueSources is additive to flag rather than a replacement.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/afbcc4e6e28a856f. Report an issue: GitHub.