{"record":{"id":"b446b556875b2161","repo":"larksuite/cli","slug":"expected-s-got-s","errorCode":null,"errorMessage":"expected <%s>, got <%s>","messagePattern":"expected <(.+?)>, got <(.+?)>","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/doc/html5_block_resources.go","lineNumber":887,"sourceCode":"\nfunc parseHTML5BlockStartTag(raw string) (html5BlockStartTag, error) {\n\ttrimmed := strings.TrimSpace(raw)\n\tselfClosing := strings.HasSuffix(trimmed, \"/>\")\n\tdecoder := xml.NewDecoder(strings.NewReader(raw))\n\tfor {\n\t\ttok, err := decoder.Token()\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn html5BlockStartTag{}, err\n\t\t}\n\t\tstart, ok := tok.(xml.StartElement)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif start.Name.Local != html5BlockTag {\n\t\t\treturn html5BlockStartTag{}, fmt.Errorf(\"expected <%s>, got <%s>\", html5BlockTag, start.Name.Local) //nolint:forbidigo // intermediate parse helper; callers wrap with typed validation errors.\n\t\t}\n\t\tattrs := make([]html5BlockAttr, 0, len(start.Attr))\n\t\tfor _, attr := range start.Attr {\n\t\t\tattrs = append(attrs, html5BlockAttr{Name: attr.Name.Local, Value: attr.Value})\n\t\t}\n\t\treturn html5BlockStartTag{Attrs: attrs, SelfClosing: selfClosing}, nil\n\t}\n\treturn html5BlockStartTag{}, fmt.Errorf(\"missing start element\") //nolint:forbidigo // intermediate parse helper; callers wrap with typed validation errors.\n}\n\nfunc parseWhiteboardStartTag(raw string) (whiteboardStartTag, error) {\n\ttrimmed := strings.TrimSpace(raw)\n\tselfClosing := strings.HasSuffix(trimmed, \"/>\")\n\tdecoder := xml.NewDecoder(strings.NewReader(raw))\n\tfor {\n\t\ttok, err := decoder.Token()\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.EOF) {","sourceCodeStart":869,"sourceCodeEnd":905,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/doc/html5_block_resources.go#L869-L905","documentation":"parseHTML5BlockStartTag parses a start-tag fragment with the XML tokenizer and requires the first element to be the expected html5 block tag (html5BlockTag, e.g. a specific container tag used by doc resource rewriting). When the fragment's root element has a different local name, it reports 'expected <X>, got <Y>'. Callers wrap this into typed validation errors.","triggerScenarios":"Doc content rewriting that extracts an HTML5 block start tag receives markup whose first element is a different tag — e.g. nested/renamed container tags, custom tags in the document, or markup that begins with a child element instead of the expected block wrapper.","commonSituations":"Feishu/Lark doc content with unexpected or legacy HTML structures, third-party pasted content with nonstandard tags, or template/normalization changes upstream producing a different root element.","solutions":["Inspect the failing fragment (the wrapped validation error includes the raw markup) and see which tag was actually present.","Ensure the content is normalized/converted to the expected doc HTML structure before the rewrite step (e.g. via the doc format converter).","If this is your pipeline feeding the command, sanitize or map nonstandard tags to the expected block tag before invoking."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Peek at the first start element before invoking the rewrite:\ndec := xml.NewDecoder(strings.NewReader(fragment))\nfor {\n    tok, err := dec.Token()\n    if err == io.EOF { log.Fatal(\"no element found\") }\n    if err != nil { log.Fatal(err) }\n    if se, ok := tok.(xml.StartElement); ok {\n        if se.Name.Local != expectedTag { log.Fatalf(\"root is <%s>, want <%s>\", se.Name.Local, expectedTag) }\n        break\n    }\n}","typeGuard":"func rootElementIs(fragment, want string) bool {\n    dec := xml.NewDecoder(strings.NewReader(fragment))\n    for {\n        tok, err := dec.Token()\n        if err != nil { return false }\n        if se, ok := tok.(xml.StartElement); ok { return se.Name.Local == want }\n    }\n}","tryCatchPattern":"// Wrap the helper error into the typed validation error the callers use:\nout, err := parseHTML5BlockStartTag(raw)\nif err != nil {\n    return errs.NewValidationError(errs.SubtypeInvalidArgument, \"invalid html5 block %q: %s\", raw, err).WithCause(err)\n}","preventionTips":["Ensure documents pass through the doc format converter so blocks use the expected wrapper tag.","Sanitize or map custom/nonstandard tags before resource rewriting.","When testing, feed real exported doc fragments, not handcrafted HTML with different roots."],"tags":["html","xml-parsing","doc-rewrite","validation"],"backgroundTag":"unexpected-html-element","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"}