projectdiscovery/katana · error
failed to strip text content
Error message
failed to strip text content
What it means
Runtime error from Normalizer.Apply: stripTextContent(firstpass) failed. stripTextContent parses the DOM-normalized HTML with goquery and removes text nodes from content elements (h1..h6, p, span, div, td, th, li, a); errors come from goquery.NewDocumentFromReader (reader issue) or doc.Html() serialization failure. This pass is what makes page hashes stable across text changes.
Source
Thrown at pkg/engine/headless/crawler/normalizer/normalizer.go:52
}
// Apply applies the normalizers to the given content
//
// It normalizes the given content by:
// - Applying the DOM normalizer
// - Applying the text normalizer
// - Denormalizing it
func (n *Normalizer) Apply(text string) (string, error) {
first := normalizeDocument(text)
firstpass, err := n.dom.Apply(first)
if err != nil {
return "", errors.Wrap(err, "failed to apply DOM normalizer")
}
secondpass, err := stripTextContent(firstpass)
if err != nil {
return "", errors.Wrap(err, "failed to strip text content")
}
thirdpass := n.text.Apply(secondpass)
fourthpass := normalizeDocument(thirdpass)
return fourthpass, nil
}
// normalizeDocument normalizes the given document by:
// - Lowercasing it
// - URL decoding it
// - HTML entity decoding it
// - Replacing all whitespace variations with a space
// - Trimming the document whitespaces
func normalizeDocument(text string) string {
// Lowercase the document
lowercased := strings.ToLower(text)
View on GitHub (pinned to e3e742739c)
Solutions
- Update katana to get the latest goquery/parser handling fixes
- Check the wrapped error to identify whether parse or serialize failed
- Skip or hash the unstripped DOM as a fallback for pages that fail stripping
- Bound page size before normalization to avoid pathological parser input
Defensive patterns
Strategy: try-catch
Validate before calling
// quick parse probe mirroring stripTextContent
if _, err := goquery.NewDocumentFromReader(strings.NewReader(html)); err != nil {
return fallback // cannot be stripped
} Type guard
func strippable(html string) bool {
_, err := goquery.NewDocumentFromReader(strings.NewReader(html))
return err == nil
} Try / catch
norm, err := normalizer.Apply(html)
if err != nil {
logger.Debug("strip failed; hashing raw html", slog.String("error", err.Error()))
norm = html
} Prevention
- Keep goquery/katana versions current
- Limit huge pages before normalization
- Fallback to unstripped hashing when stripping fails
- Watch for documents that fail parse vs serialize and file issues accordingly
When it happens
Trigger: 1) goquery.NewDocumentFromReader errors parsing the first-pass HTML. 2) doc.Html() fails to serialize the modified document. 3) Extremely large or pathological documents exhausting the parser. 4) Prior passes produced input the parser rejects (nested transformation bug).
Common situations: Crawling huge or deeply nested pages; sites emitting binary garbage misdetected as HTML; katana versions with stripTextContent edge-case bugs.
Related errors
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/9f6452dd000982ce.
Report an issue: GitHub.