{"record":{"id":"4dceaae0a50385e8","repo":"larksuite/cli","slug":"unsupported-patch-op-q","errorCode":null,"errorMessage":"unsupported patch op %q","messagePattern":"unsupported patch op %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/patch.go","lineNumber":145,"sourceCode":"\t\t\treturn fmt.Errorf(\"replace_inline: %w\", err)\n\t\t}\n\t\treturn replaceInline(dctx, snapshot, partID, op.Path, op.CID, op.FileName, op.ContentType)\n\tcase \"remove_inline\":\n\t\tpartID, err := resolveTarget(snapshot, op.Target)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"remove_inline: %w\", err)\n\t\t}\n\t\treturn removeInline(snapshot, partID)\n\tcase \"insert_signature\":\n\t\treturn insertSignatureOp(snapshot, op)\n\tcase \"remove_signature\":\n\t\treturn removeSignatureOp(snapshot)\n\tcase \"set_calendar\":\n\t\treturn applyCalendarSet(snapshot, op.CalendarICS)\n\tcase \"remove_calendar\":\n\t\treturn applyCalendarRemove(snapshot)\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported patch op %q\", op.Op)\n\t}\n\treturn nil\n}\n\nfunc ensureHeaderEditable(name string, options PatchOptions) error {\n\tif protectedHeaders[strings.ToLower(strings.TrimSpace(name))] && !options.AllowProtectedHeaderEdits {\n\t\treturn fmt.Errorf(\"header %q is protected; rerun with allow_protected_header_edits\", name)\n\t}\n\treturn nil\n}\n\nfunc setRecipients(snapshot *DraftSnapshot, field string, addrs []Address) error {\n\tfield = strings.ToLower(strings.TrimSpace(field))\n\tif !isRecipientField(field) {\n\t\treturn fmt.Errorf(\"recipient field must be one of to/cc/bcc\")\n\t}\n\tnormalized := make([]Address, 0, len(addrs))\n\tseen := map[string]bool{}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/patch.go#L127-L163","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nop := PatchOp{Op: \"setHeader\", ...}\n// after\nop := PatchOp{Op: \"set_header\", ...}","handlingStrategy":"validation","validationCode":"var supportedOps = map[string]bool{\n  \"set_subject\": true, \"set_recipients\": true, \"add_recipient\": true,\n  \"append_body\": true, \"set_header\": true, \"remove_header\": true,\n  \"remove_attachment\": true, \"add_inline\": true, \"replace_inline\": true,\n  \"remove_inline\": true, \"insert_signature\": true, \"remove_signature\": true,\n  \"set_calendar\": true, \"remove_calendar\": true,\n}\nfunc opSupported(op string) bool { return supportedOps[op] }","typeGuard":"func knownPatchOp(op PatchOp) bool { return supportedOps[op.Op] }\n// filter: for i := range ops { if !knownPatchOp(ops[i]) { return fmt.Errorf(\"unknown op %q\", ops[i].Op) } }","tryCatchPattern":"if err := Apply(ctx, dctx, ops, opts); err != nil {\n    var ue *unsupportedOpError\n    if strings.Contains(err.Error(), \"unsupported patch op\") {\n        return fmt.Errorf(\"check op name against supported list / version mismatch: %w\", err)\n    }\n    return err\n}","preventionTips":["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."],"tags":["draft-patch","validation","api-mismatch"],"backgroundTag":"unsupported-operation","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}