{"record":{"id":"7da7fd7be055c402","repo":"PuerkitoBio/goquery","slug":"goquery-failed-to-parse-html","errorCode":null,"errorMessage":"goquery: failed to parse HTML: ","messagePattern":"goquery: failed to parse HTML: ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"manipulation.go","lineNumber":571,"sourceCode":"\t\t\tcontents.wrapAllNodes(ns...)\n\t\t} else {\n\t\t\ts.AppendNodes(cloneNode(ns[0]))\n\t\t}\n\t})\n\n\treturn s\n}\n\nfunc parseHtml(h string) []*html.Node {\n\treturn parseHtmlWithContext(h, &html.Node{Type: html.ElementNode})\n}\n\nfunc parseHtmlWithContext(h string, context *html.Node) []*html.Node {\n\t// Errors are only returned when the io.Reader returns any error besides\n\t// EOF, but strings.Reader never will\n\tnodes, err := html.ParseFragment(strings.NewReader(h), context)\n\tif err != nil {\n\t\tpanic(\"goquery: failed to parse HTML: \" + err.Error())\n\t}\n\treturn nodes\n}\n\n// Get the first child that is an ElementNode\nfunc getFirstChildEl(n *html.Node) *html.Node {\n\tc := n.FirstChild\n\tfor c != nil && c.Type != html.ElementNode {\n\t\tc = c.NextSibling\n\t}\n\treturn c\n}\n\n// Deep copy a slice of nodes.\nfunc cloneNodes(ns []*html.Node) []*html.Node {\n\tcns := make([]*html.Node, 0, len(ns))\n\n\tfor _, n := range ns {","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/PuerkitoBio/goquery/blob/738783cbc3c6244dea65b66306dae4fd0f84e7e3/manipulation.go#L553-L589","documentation":"parseHtmlWithContext panics when html.ParseFragment returns an error while parsing an HTML fragment into a context node. Per golang.org/x/net/html, ParseFragment only errors on a reader failure other than EOF, and since parsing reads from a strings.Reader this should practically never happen — the panic is a defensive assertion for an impossible condition.","triggerScenarios":"Indirectly triggered by any manipulation API that parses HTML fragments: AfterHtml, BeforeHtml, PrependHtml, AppendHtml, WrapAllHtml, WrapInnerHtml, ReplaceWithHtml, or parseHtml/cachedParseHtmlWithContext — only if strings.NewReader somehow fails, which cannot occur for in-memory strings.","commonSituations":"Effectively unreachable in real use; if a stack trace surfaces it, it usually indicates a custom/altered fork of the library, memory corruption, or a modified golang.org/x/net/html package where ParseFragment returns non-EOF errors.","solutions":["Report/reproduce the exact input and stack trace; this is an internal invariant break, not a caller error.","Verify you are using unmodified releases of goquery and golang.org/x/net; upgrade both to latest.","If you need safe error handling instead of a panic, pre-parse with html.ParseFragment yourself or use NewDocumentFromReader paths that return errors normally.","Recover from the panic at a boundary if processing untrusted input through a fork."],"exampleFix":"// before\ndoc.Find(\"div\").WrapAllHtml(userSuppliedHtml) // panics on parse failure in forks\n\n// after\nfunc safeWrapAll(doc *goquery.Document, sel, htmlStr string) (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"fragment parse failed: %v\", r)\n\t\t}\n\t}()\n\tdoc.Find(sel).WrapAllHtml(htmlStr)\n\treturn nil\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tif errStr, ok := r.(string); ok && strings.HasPrefix(errStr, \"goquery: failed to parse HTML:\") {\n\t\t\terr = errors.New(errStr)\n\t\t\treturn\n\t\t}\n\t\tpanic(r)\n\t}\n}()","preventionTips":["Use official goquery and golang.org/x/net releases; this panic is practically unreachable otherwise.","Keep fragment HTML as plain strings (strings.Reader never errors), which is what goquery already does.","If processing a fork, convert panics to errors at your API boundary with defer/recover."],"tags":["go","goquery","html-parsing","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"738783cbc3c6244dea65b66306dae4fd0f84e7e3","analyzedAt":"2026-09-06T07:49:12.071Z","contentChangedAt":"2026-09-06T07:49:12.071Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}