gastownhall/beads · error

invalid --set-metadata: expected key=value, got %q

Error message

invalid --set-metadata: expected key=value, got %q

What it means

bd update's --set-metadata flag accepts one key=value pair per flag occurrence. parseSetMetadataFlags splits each flag value on '=' and rejects any entry that has no '=' separator or an empty key, because metadata cannot be assigned without both a key and a value.

Source

Thrown at cmd/bd/update.go:799

	if value == nil {
		return setField[*time.Time](nil), true
	}
	at, ok := value.(time.Time)
	if !ok {
		return issueops.Field[*time.Time]{}, false
	}
	return setField(&at), true
}

// parseSetMetadataFlags splits --set-metadata key=value pairs, matching
// storage.ApplyMetadataEdits' parsing so the CLI contract is unchanged. Values
// are always stored as JSON strings (GH#4146).
func parseSetMetadataFlags(flags []string) (map[string]json.RawMessage, error) {
	set := make(map[string]json.RawMessage, len(flags))
	for _, flag := range flags {
		key, value, ok := strings.Cut(flag, "=")
		if !ok || key == "" {
			return nil, fmt.Errorf("invalid --set-metadata: expected key=value, got %q", flag)
		}
		set[key] = storage.MetadataEditValue(value)
	}
	return set, nil
}

func replacesExistingNotes(existing string, fields map[string]any) bool {
	newNotes, replacing := fields["notes"].(string)
	return replacing && existing != "" && newNotes != existing
}

func warnNotesReplacement(id string) {
	fmt.Fprintf(os.Stderr, "warning: %s: --notes replaced existing notes (use --append-notes to preserve history)\n", id) //nolint:gosec // G705: stderr, not a browser context
}

// ExitGuardMismatch is the exit code when a `bd update` run failed solely
// because --if-assignee/--if-status guards did not match: the precondition no
// longer held, nothing was written, and retrying is pointless — another actor

View on GitHub (pinned to 71377f2769)

Solutions

  1. Repeat the flag once per pair with an explicit '=': --set-metadata key=value
  2. Quote the pair so the shell doesn't split it: --set-metadata "key=some value"
  3. Check `bd update --help` for the exact --set-metadata syntax

Example fix

// before
bd update bd-42 --set-metadata priority
// after
bd update bd-42 --set-metadata priority=high
Defensive patterns

Strategy: validation

Validate before calling

for _, pair := range setMetadataFlags {
    if !strings.Contains(pair, "=") || strings.SplitN(pair, "=", 2)[0] == "" {
        return fmt.Errorf("bad --set-metadata pair %q: use key=value", pair)
    }
}

Prevention

When it happens

Trigger: Running `bd update <id> --set-metadata foo` (no '='), `--set-metadata =bar` (empty key), or `--set-metadata ""` (empty string) via buildUpdatePatch or proxiedUpdatePatch.

Common situations: Shell quoting stripping the '=' (e.g. `--set-metadata "key="` is fine but `--set-metadata key` after variable expansion loses the value); users copying `--metadata key value` style from other CLIs; typos like a space instead of '='.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/f397d51be8a67642. Report an issue: GitHub.