swc-project/swc · warning · Error

Start tag "{tag_name}" seen without a "ruby" element being o

Error message

Start tag "{tag_name}" seen without a "ruby" element being open

What it means

A start tag `rb` or `rtc` was seen while no `ruby` element is in scope (parser/mod.rs:4066-4081). Ruby annotation tags are only meaningful inside `<ruby>`, so the spec makes this a parse error (`StartTagSeenWithoutRuby`); the parser still inserts the element, now as ordinary body content.

Source

Thrown at crates/swc_html_parser/src/parser/mod.rs:4072

                    // implied end tags. If the current node is not now a ruby element, this is a
                    // parse error.
                    //
                    // Insert an HTML element for the token.
                    Token::StartTag {
                        tag_name,
                        is_self_closing,
                        ..
                    } if matches!(&**tag_name, "rb" | "rtc") => {
                        let is_scope = self.open_elements_stack.has_in_scope("ruby");

                        if is_scope {
                            self.open_elements_stack.generate_implied_end_tags();
                        }

                        match self.open_elements_stack.items.last() {
                            Some(node) if !is_html_element!(node, "ruby") => {
                                if !is_scope {
                                    self.errors.push(Error::new(
                                        token_and_info.span,
                                        ErrorKind::StartTagSeenWithoutRuby(tag_name.clone()),
                                    ));
                                } else {
                                    self.errors.push(Error::new(
                                        token_and_info.span,
                                        ErrorKind::UnclosedChildrenInRuby,
                                    ));
                                }
                            }
                            _ => {}
                        }

                        self.insert_html_element(token_and_info)?;
                        maybe_allow_self_closing!(is_self_closing, tag_name);
                    }
                    // A start tag whose tag name is one of: "rp", "rt"
                    //

View on GitHub (pinned to 5176682b65)

Solutions

  1. Wrap the annotation markup in `<ruby>...</ruby>`
  2. Fix the component/fragment so `<rb>`/`<rtc>` are always rendered inside a ruby element
  3. When parsing fragments, give the parser the correct context element so scoping matches the final document
  4. Lint for rb/rt/rp/rtc tags that lack an ancestor ruby

Example fix

<!-- before -->
<rb>漢</rb><rt>かん</rt>

<!-- after -->
<ruby><rb>漢</rb><rt>かん</rt></ruby>
Defensive patterns

Strategy: validation

Validate before calling

// Ensure rb/rtc tokens appear only inside a <ruby> wrapper
fn ruby_tags_orphaned(src: &str) -> bool {
    let mut ruby = 0i32;
    for tag in html_tag_tokens(src) {
        match tag {
            Start(ref n) if n == "ruby" => ruby += 1,
            End(ref n) if n == "ruby" => ruby = ruby.saturating_sub(1),
            Start(ref n) if matches!(n.as_str(), "rb"|"rtc") && ruby == 0 => return true,
            _ => {}
        }
    }
    false
}

Type guard

fn is_rb_outside_ruby(e: &Error) -> bool {
    matches!(
        e.kind,
        ErrorKind::StartTagSeenWithoutRuby(ref t) if matches!(&**t, "rb"|"rtc")
    )
}

Try / catch

let doc = parser.parse_document()?;
if parser.take_errors().into_iter().any(is_rb_outside_ruby) {
    return Err(ContentRejected::RubyMarkupMissingWrapper);
}

Prevention

When it happens

Trigger: `<rb>` or `<rtc>` appearing outside any `<ruby>`: e.g. `<p><rb>漢</rb></p>`, or ruby markup assembled from separate strings/fragments where the `<ruby>` wrapper is missing or was closed too early.

Common situations: Building CJK furigana/annotation markup programmatically (dictionaries, language-learning apps) and forgetting the `<ruby>` wrapper; parsing innerHTML fragments that were extracted from a ruby context; template partials that render only the `rb`/`rt` pieces.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/6d5a287ffb06d9fe. Report an issue: GitHub.