larksuite/cli · info

marshal key %q: %w

Error message

marshal key %q: %w

What it means

OrderedMap.MarshalJSON serializes the map while preserving insertion order by marshaling each key separately. This error wraps a failure from json.Marshal on an individual key. In practice keys are Go strings, which always marshal successfully, so this is a defensive guard that should virtually never fire.

Source

Thrown at internal/schema/types.go:133

		return []byte("{}"), nil
	}
	keys := o.Order
	if len(keys) == 0 {
		keys = make([]string, 0, len(o.Map))
		for k := range o.Map {
			keys = append(keys, k)
		}
		sort.Strings(keys)
	}
	var buf bytes.Buffer
	buf.WriteByte('{')
	for i, k := range keys {
		if i > 0 {
			buf.WriteByte(',')
		}
		keyJSON, err := json.Marshal(k)
		if err != nil {
			return nil, fmt.Errorf("marshal key %q: %w", k, err)
		}
		buf.Write(keyJSON)
		buf.WriteByte(':')
		valJSON, err := json.Marshal(o.Map[k])
		if err != nil {
			return nil, fmt.Errorf("marshal value for %q: %w", k, err)
		}
		buf.Write(valJSON)
	}
	buf.WriteByte('}')
	return buf.Bytes(), nil
}

// UnmarshalJSON parses an object preserving key order via json.Decoder.Token().
// Used for round-tripping in tests (and future golden update flows).
func (o *OrderedProps) UnmarshalJSON(data []byte) error {
	dec := json.NewDecoder(bytes.NewReader(data))
	tok, err := dec.Token()

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Inspect the wrapped %w cause to identify the unmarshalable key value
  2. Confirm keys are plain strings; strings are always JSON-marshalable
  3. If you changed the key type, add a MarshalJSON method to the key type or convert keys to string before insertion

Example fix

// before (custom key type that fails to marshal)
type Key struct{ ID chan int }
// after
type Key struct{ ID string }
func (k Key) MarshalJSON() ([]byte, error) { return json.Marshal(k.ID) }
Defensive patterns

Strategy: try-catch

Try / catch

data, err := json.Marshal(om)
if err != nil {
	var mErr *fmt.wrapError
	if errors.As(err, &mErr) && strings.Contains(err.Error(), "marshal key") {
		// fix key type in OrderedMap
	}
	return err
}

Prevention

When it happens

Trigger: Calling json.Marshal (or any encoding that invokes MarshalJSON) on an internal/schema OrderedMap whose key cannot be JSON-encoded. With the current string-typed keys this is unreachable; it would only fire if the key type changed to a non-JSON-serializable type (e.g. chan, func, or a type with a failing MarshalJSON).

Common situations: Developers encounter this only via the wrapped cause in a larger marshal failure chain, typically while debugging custom schema property maps after modifying the OrderedMap key type.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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