urfave/cli · error

item %q is missing separator %q

Error message

item %q is missing separator %q

What it means

For map flags (MapFlag), each value must be a key=value pair. Set splits the raw string into items (honoring the slice separator, default ','), then splits each item on the key/value separator (default '='). If an item contains no separator, it returns "item %q is missing separator %q".

Source

Thrown at flag_map_impl.go:82

	}

	mvc := &i.multiValueConfig
	keyValueSeparator := mvc.MapFlagKeyValueSeparator
	if len(keyValueSeparator) == 0 {
		keyValueSeparator = defaultMapFlagKeyValueSeparator
	}

	tracef(
		"splitting map value '%s', keyValueSeparator '%s', slice separator '%s', disable separator:%v",
		value,
		keyValueSeparator,
		mvc.SliceFlagSeparator,
		mvc.DisableSliceFlagSeparator,
	)
	for _, item := range flagSplitMultiValues(value, mvc.SliceFlagSeparator, mvc.DisableSliceFlagSeparator) {
		key, value, ok := strings.Cut(item, keyValueSeparator)
		if !ok {
			return fmt.Errorf("item %q is missing separator %q", item, keyValueSeparator)
		}
		if err := i.value.Set(value); err != nil {
			return err
		}
		(*i.dict)[key] = i.value.Get().(T)
	}

	return nil
}

// String returns a readable representation of this value (for usage defaults)
func (i *MapBase[T, C, VC]) String() string {
	v := i.Value()
	var t T
	if reflect.TypeOf(t).Kind() == reflect.String {
		return fmt.Sprintf("%v", v)
	}
	return fmt.Sprintf("%T{%s}", v, i.ToString(v))

View on GitHub (pinned to 1a4deb4f5a)

Solutions

  1. Ensure every comma-separated item is in key=value form, e.g. --opts a=1,b=2.
  2. Quote the whole value in the shell so '=' and ',' survive: --opts "a=1,b=2".
  3. Check SliceFlagSeparator configuration; if the separator was changed (or DisableSliceFlagSeparator set), items must be split on the configured separator.
  4. Inspect the input for stray commas producing empty or malformed items and remove them.

Example fix

// before
myapp --opts key1,key2=value

// after
myapp --opts "key1=value1,key2=value2"
Defensive patterns

Strategy: validation

Validate before calling

// shell: validate every comma-separated item contains '='
value="key1=v1,key2=v2"
IFS=',' read -ra items <<< "$value"
for it in "${items[@]}"; do
  [[ "$it" == *=* ]] || { echo "bad map item (needs key=value): $it" >&2; exit 1; }
done

Type guard

func validMapValue(v string, sep string) bool {
    for _, item := range strings.Split(v, sep) {
        if !strings.Contains(item, "=") { return false }
    }
    return true
}

Try / catch

if err := cmd.Run(ctx, os.Args); err != nil {
    if strings.Contains(err.Error(), "is missing separator") {
        fmt.Fprintln(os.Stderr, "map flags need key=value pairs, e.g. --opts a=1,b=2")
        os.Exit(2)
    }
    return err
}

Prevention

When it happens

Trigger: Passing a map flag value without '=' in one of the comma-separated items, e.g. `--opts foo` or `--opts a=1,b` (the item "b" has no '='), or an empty item like `--opts a=1,,b=2`.

Common situations: Users familiar with slice flags passing bare values to a map flag; shell quoting stripping the '=' or splitting items unexpectedly; copy-pasted config where the last pair lost its value (e.g. `a=1,b=` still works, but trailing `,b` does not).

Related errors


AI-assisted analysis of urfave/cli@1a4deb4f5a (2026-08-31). Data as JSON: /api/errors/bad5dfe9c69b8ae1. Report an issue: GitHub.