Y2Z/monolith · error

unable to serialize DOM into buffer

Error message

unable to serialize DOM into buffer

What it means

`add_favicon` serializes the document DOM back to bytes with html5ever's `serialize` and panics via `.expect("unable to serialize DOM into buffer")` when serialization returns `Err`. This happens when the DOM tree is malformed for the serializer (corrupt tree produced by parsing bad input or by earlier manipulation). The panic aborts document processing rather than skipping the favicon injection.

Source

Thrown at src/html.rs:49

    Favicon,
    Preload,
    Stylesheet,
    Manifest,
}

pub struct SrcSetItem<'a> {
    pub path: &'a str,
    pub descriptor: &'a str, // Width or pixel density descriptor
}

pub fn add_favicon(document: &Handle, favicon_data_url: String) -> RcDom {
    let mut buf: Vec<u8> = Vec::new();
    serialize(
        &mut buf,
        &SerializableHandle::from(document.clone()),
        SerializeOpts::default(),
    )
    .expect("unable to serialize DOM into buffer");

    let dom = html_to_dom(&buf, "utf-8".to_string());
    for head in find_nodes(&dom.document, vec!["html", "head"]).iter() {
        let favicon_node = create_element(
            &dom,
            QualName::new(None, ns!(), LocalName::from("link")),
            vec![
                Attribute {
                    name: QualName::new(None, ns!(), LocalName::from("rel")),
                    value: format_tendril!("icon"),
                },
                Attribute {
                    name: QualName::new(None, ns!(), LocalName::from("href")),
                    value: format_tendril!("{}", favicon_data_url),
                },
            ],
        );

View on GitHub (pinned to a6fc8d0095)

Solutions

  1. Validate the input is real HTML (correct Content-Type, decompressed if Content-Encoding: gzip) before calling `create_monolithic_document_from_data`.
  2. Re-parse the document from the original bytes with `html_to_dom` instead of serializing a mutated DOM.
  3. Serialize a valid `SerializableHandle` (whole document) rather than a detached/odd node.
  4. Catch the panic with `catch_unwind` if you must tolerate bad inputs, and/or file an issue with the failing HTML upstream.

Example fix

// before
serialize(
    &mut buf,
    &SerializableHandle::from(document.clone()),
    SerializeOpts::default(),
)
.expect("unable to serialize DOM into buffer");
// after
if serialize(
    &mut buf,
    &SerializableHandle::from(document.clone()),
    SerializeOpts::default(),
)
.is_err()
{
    eprintln!("skipping favicon: DOM not serializable");
    return;
}
Defensive patterns

Strategy: try-catch

Validate before calling

fn looks_like_html(bytes: &[u8], content_type: &str) -> bool {
    content_type.starts_with("text/html")
        && !bytes.starts_with(&[0x1f, 0x8b]) // not gzip
        && std::str::from_utf8(bytes)
            .map(|s| {
                let l = s.to_ascii_lowercase();
                l.contains("<html") || l.contains("<!doctype")
            })
            .unwrap_or(false)
}

Type guard

fn is_valid_html_input(data: &[u8]) -> bool {
    std::str::from_utf8(data)
        .map(|s| {
            let l = s.trim_start().to_ascii_lowercase();
            l.starts_with("<!doctype html") || l.contains("<html")
        })
        .unwrap_or(false)
}

Try / catch

let result = std::panic::catch_unwind(|| {
    create_monolithic_document_from_data(&data, &url)
});
match result {
    Ok(doc) => use_document(doc),
    Err(_) => eprintln!("monolith panicked serializing DOM (favicon step); skipping document"),
}

Prevention

When it happens

Trigger: Calling `create_monolithic_document_from_data` (which calls `add_favicon`) on input whose parsed DOM fails html5ever serialization — typically corrupt, truncated, or binary data parsed as HTML, or an error writing into the in-memory `Vec<u8>` buffer.

Common situations: Pointing monolith at non-HTML responses (images, PDFs, gzipped bodies not decompressed, error pages) that parse into a broken tree; HTML with exotic encodings or unencodable characters; server returning truncated HTML.

Related errors


AI-assisted analysis of Y2Z/monolith@a6fc8d0095 (2026-09-05). Data as JSON: /api/errors/c1c531a4a39369c3. Report an issue: GitHub.