larksuite/cli · error

marshal value for %q: %w

Error message

marshal value for %q: %w

What it means

OrderedMap.MarshalJSON marshals each value (a schema Property) after its key. If json.Marshal of the Property fails, the error is wrapped with the failing key name so the offending entry can be located. This fires when a Property contains a field that cannot be JSON-encoded.

Source

Thrown at internal/schema/types.go:139

			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()
	if err != nil {
		return err
	}
	if delim, ok := tok.(json.Delim); !ok || delim != '{' {
		return fmt.Errorf("expected object, got %v", tok)
	}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Read the %q key in the message to find the offending entry in the map
  2. Inspect the wrapped %w cause from json.Marshal for the specific unsupported value
  3. Fix the Property's MarshalJSON implementation or replace the unmarshalable field
  4. Add a unit test marshaling the full OrderedMap to catch this at build time

Example fix

// before
func (p Property) MarshalJSON() ([]byte, error) { return nil, errors.New("unsupported") }
// after
func (p Property) MarshalJSON() ([]byte, error) { return json.Marshal(p.fields()) }
Defensive patterns

Strategy: try-catch

Validate before calling

for k, v := range om.Map {
	if _, err := json.Marshal(v); err != nil {
		return fmt.Errorf("entry %q is not JSON-marshalable: %w", k, err)
	}
}

Type guard

func marshalable(v any) bool {
	_, err := json.Marshal(v)
	return err == nil
}

Try / catch

data, err := json.Marshal(om)
if err != nil {
	var keyErr interface{ Error() string }
	if strings.Contains(err.Error(), "marshal value for") {
		// key name is quoted between 'for ' and the next ':' — locate and fix that Property
	}
	return err
}

Prevention

When it happens

Trigger: Marshaling an OrderedMap where o.Map[k] is a Property (or contains nested values like custom marshalers, channels, funcs, or cyclic structures handled via MarshalJSON) whose json.Marshal returns an error.

Common situations: Custom Property extensions or injected values with broken MarshalJSON implementations; json.Marshaler that returns an error; unsupported types smuggled into interface fields.

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/b22c851634842247. Report an issue: GitHub.