larksuite/cli · error
unsupported patch op %q
Error message
unsupported patch op %q
What it means
Guard in applyOp: the patch op's Op name matches none of the supported operations, so the patch cannot be applied to the draft snapshot.
Source
Thrown at shortcuts/mail/draft/patch.go:145
return fmt.Errorf("replace_inline: %w", err)
}
return replaceInline(dctx, snapshot, partID, op.Path, op.CID, op.FileName, op.ContentType)
case "remove_inline":
partID, err := resolveTarget(snapshot, op.Target)
if err != nil {
return fmt.Errorf("remove_inline: %w", err)
}
return removeInline(snapshot, partID)
case "insert_signature":
return insertSignatureOp(snapshot, op)
case "remove_signature":
return removeSignatureOp(snapshot)
case "set_calendar":
return applyCalendarSet(snapshot, op.CalendarICS)
case "remove_calendar":
return applyCalendarRemove(snapshot)
default:
return fmt.Errorf("unsupported patch op %q", op.Op)
}
return nil
}
func ensureHeaderEditable(name string, options PatchOptions) error {
if protectedHeaders[strings.ToLower(strings.TrimSpace(name))] && !options.AllowProtectedHeaderEdits {
return fmt.Errorf("header %q is protected; rerun with allow_protected_header_edits", name)
}
return nil
}
func setRecipients(snapshot *DraftSnapshot, field string, addrs []Address) error {
field = strings.ToLower(strings.TrimSpace(field))
if !isRecipientField(field) {
return fmt.Errorf("recipient field must be one of to/cc/bcc")
}
normalized := make([]Address, 0, len(addrs))
seen := map[string]bool{}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Check the op name spelling and casing against the supported list in applyOp (shortcuts/mail/draft/patch.go).
- Validate op names against an allowlist before calling Apply.
- Upgrade or downgrade so client op schema and library version match.
- Log the full op JSON to spot empty or mangled Op fields after deserialization.
Example fix
// before
op := PatchOp{Op: "setHeader", ...}
// after
op := PatchOp{Op: "set_header", ...} Defensive patterns
Strategy: validation
Validate before calling
var supportedOps = map[string]bool{
"set_subject": true, "set_recipients": true, "add_recipient": true,
"append_body": true, "set_header": true, "remove_header": true,
"remove_attachment": true, "add_inline": true, "replace_inline": true,
"remove_inline": true, "insert_signature": true, "remove_signature": true,
"set_calendar": true, "remove_calendar": true,
}
func opSupported(op string) bool { return supportedOps[op] } Type guard
func knownPatchOp(op PatchOp) bool { return supportedOps[op.Op] }
// filter: for i := range ops { if !knownPatchOp(ops[i]) { return fmt.Errorf("unknown op %q", ops[i].Op) } } Try / catch
if err := Apply(ctx, dctx, ops, opts); err != nil {
var ue *unsupportedOpError
if strings.Contains(err.Error(), "unsupported patch op") {
return fmt.Errorf("check op name against supported list / version mismatch: %w", err)
}
return err
} Prevention
- Keep op names in shared constants, never inline strings.
- Validate op names against an allowlist before calling Apply.
- Keep client op-schema version in sync with the library version.
- Log raw op JSON when deserializing to catch empty/mangled Op fields.
When it happens
Trigger: Calling Apply with a PatchOp whose Op string is not one of set_subject, set_recipients, add_recipient, append_body, set_header, remove_header, remove_attachment, add_inline, replace_inline, remove_inline, insert_signature, remove_signature, set_calendar, remove_calendar — e.g. a typo like 'setheader' or an op from a newer/older schema version.
Common situations: Typos in hand-written op names; ops deserialized from JSON with different casing or renamed keys; client and library versions out of sync so the client emits an op this build does not know.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- set_calendar: event_start must be a valid ISO 8601 timestamp
- set_calendar: event_end must be a valid ISO 8601 timestamp
- set_calendar: event_end must be after event_start
- unsupported op %q
- recipient field must be one of to/cc/bcc
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/4dceaae0a50385e8.
Report an issue: GitHub.