Tencent/WeKnora · warning

readability parse: %w

Error message

readability parse: %w

What it means

Returned by extractArticle when go-readability cannot parse the fetched article page into a DOM. readability.FromReader parses the HTML with golang-net-html and runs the readability scoring algorithm; a parse error means the bytes are not valid HTML/XML at all (e.g. binary data, a JSON error page, or corrupt encoding), not merely 'no article found' (that is error 715).

Source

Thrown at internal/datasource/connector/rss/client.go:112

// fetchFeed retrieves the raw bytes of a feed document.
func (c *client) fetchFeed(ctx context.Context, feedURL string) ([]byte, error) {
	return c.fetch(ctx, feedURL, maxFeedSize, true)
}

// extractArticle fetches an article page and returns the readability-cleaned
// main content as HTML, plus the extracted title (may be empty). Returns an
// error if the page can't be fetched or no readable content is found, so the
// caller can fall back to feed-provided content.
func (c *client) extractArticle(ctx context.Context, articleURL string) (contentHTML, title string, err error) {
	body, err := c.fetch(ctx, articleURL, maxArticleSize, false)
	if err != nil {
		return "", "", err
	}

	pageURL, _ := url.Parse(articleURL)
	article, err := readability.FromReader(bytes.NewReader(body), pageURL)
	if err != nil {
		return "", "", fmt.Errorf("readability parse: %w", err)
	}
	if article.Node == nil {
		return "", "", fmt.Errorf("no readable content extracted")
	}

	var buf bytes.Buffer
	if err := article.RenderHTML(&buf); err != nil {
		return "", "", fmt.Errorf("render article html: %w", err)
	}
	return buf.String(), article.Title(), nil
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check what the URL actually returns (curl -i) — if it is not HTML (PDF/image/JSON), exclude that item or handle non-HTML link types before calling extractArticle.
  2. Fix charset declarations on the source site or transcode the body to UTF-8 before parsing.
  3. If a bot-protection page is the cause, the content cannot be extracted by design; fall back to feed-provided summary content, as the caller resolveItem does.
  4. Verify the fetch got a real article page, not an error page, by sniffing Content-Type before parsing.

Example fix

// before
contentHTML, title, err := cli.extractArticle(ctx, item.Link)
if err != nil {
    contentHTML = item.Content
}
// after
ct := respHeader.Get("Content-Type")
if strings.Contains(ct, "text/html") {
    contentHTML, title, err = cli.extractArticle(ctx, item.Link)
}
if err != nil || contentHTML == "" {
    contentHTML = item.Content // feed-provided fallback
}
Defensive patterns

Strategy: fallback

Validate before calling

func isHTMLContent(resp *http.Response) bool {
    ct := resp.Header.Get("Content-Type")
    return strings.Contains(ct, "text/html") || strings.Contains(ct, "application/xhtml")
}

Try / catch

contentHTML, title, err := cli.extractArticle(ctx, item.Link)
if err != nil {
    log.Warnf("extract %s failed: %v; falling back to feed content", item.Link, err)
    contentHTML, title = item.Content, item.Title
}

Prevention

When it happens

Trigger: The article URL returned non-HTML content (a PDF, image, JSON API error, or plain text); the page uses an encoding the parser mangles into invalid markup; or the fetch returned an HTML error page so broken that the HTML parser itself fails.

Common situations: Feed item links point to PDFs or image attachments; sites behind bot protection serving binary challenge pages; legacy feeds with misdeclared charsets (e.g. claiming UTF-8 while serving GBK); article URL pointing at a JSON REST endpoint.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/1d935b227c3daf92. Report an issue: GitHub.