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
- Validate the input is real HTML (correct Content-Type, decompressed if Content-Encoding: gzip) before calling `create_monolithic_document_from_data`.
- Re-parse the document from the original bytes with `html_to_dom` instead of serializing a mutated DOM.
- Serialize a valid `SerializableHandle` (whole document) rather than a detached/odd node.
- 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
- Only feed text/html responses into monolith; skip binary/gzip/error pages.
- Decompress Content-Encoding bodies before parsing.
- Validate the body is UTF-8 HTML before processing.
- Keep monolith and html5ever versions in sync and tested against your target pages.
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
- Unable to serialize DOM into buffer
- Time went backwards
- Failed to initialize HTTP client
- unable to read file
- could not prepare output
AI-assisted analysis of Y2Z/monolith@a6fc8d0095 (2026-09-05).
Data as JSON: /api/errors/c1c531a4a39369c3.
Report an issue: GitHub.