larksuite/cli · error
expected <%s>, got <%s>
Error message
expected <%s>, got <%s>
What it means
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.
Source
Thrown at shortcuts/doc/html5_block_resources.go:887
func parseHTML5BlockStartTag(raw string) (html5BlockStartTag, error) {
trimmed := strings.TrimSpace(raw)
selfClosing := strings.HasSuffix(trimmed, "/>")
decoder := xml.NewDecoder(strings.NewReader(raw))
for {
tok, err := decoder.Token()
if err != nil {
if errors.Is(err, io.EOF) {
break
}
return html5BlockStartTag{}, err
}
start, ok := tok.(xml.StartElement)
if !ok {
continue
}
if start.Name.Local != html5BlockTag {
return html5BlockStartTag{}, fmt.Errorf("expected <%s>, got <%s>", html5BlockTag, start.Name.Local) //nolint:forbidigo // intermediate parse helper; callers wrap with typed validation errors.
}
attrs := make([]html5BlockAttr, 0, len(start.Attr))
for _, attr := range start.Attr {
attrs = append(attrs, html5BlockAttr{Name: attr.Name.Local, Value: attr.Value})
}
return html5BlockStartTag{Attrs: attrs, SelfClosing: selfClosing}, nil
}
return html5BlockStartTag{}, fmt.Errorf("missing start element") //nolint:forbidigo // intermediate parse helper; callers wrap with typed validation errors.
}
func parseWhiteboardStartTag(raw string) (whiteboardStartTag, error) {
trimmed := strings.TrimSpace(raw)
selfClosing := strings.HasSuffix(trimmed, "/>")
decoder := xml.NewDecoder(strings.NewReader(raw))
for {
tok, err := decoder.Token()
if err != nil {
if errors.Is(err, io.EOF) {View on GitHub (pinned to 7fd6ef3c07)
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.
Defensive patterns
Strategy: validation
Validate before calling
// Peek at the first start element before invoking the rewrite:
dec := xml.NewDecoder(strings.NewReader(fragment))
for {
tok, err := dec.Token()
if err == io.EOF { log.Fatal("no element found") }
if err != nil { log.Fatal(err) }
if se, ok := tok.(xml.StartElement); ok {
if se.Name.Local != expectedTag { log.Fatalf("root is <%s>, want <%s>", se.Name.Local, expectedTag) }
break
}
} Type guard
func rootElementIs(fragment, want string) bool {
dec := xml.NewDecoder(strings.NewReader(fragment))
for {
tok, err := dec.Token()
if err != nil { return false }
if se, ok := tok.(xml.StartElement); ok { return se.Name.Local == want }
}
} Try / catch
// Wrap the helper error into the typed validation error the callers use:
out, err := parseHTML5BlockStartTag(raw)
if err != nil {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid html5 block %q: %s", raw, err).WithCause(err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- missing start element
- Invalid column: {column!r}
- Invalid column index: {index}
- anchor outside sheet: {position!r}
- Missing row_count/column_count for sheet {sheet_title(sheet)
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/b446b556875b2161.
Report an issue: GitHub.