Tencent/WeKnora · error

fetch feed %s: %w

Error message

fetch feed %s: %w

What it means

Returned by Connector.Validate when fetching one of the configured feed URLs fails. Validate fetches every feed in the config and wraps any underlying client error (SSRF rejection, invalid URL, transport failure, HTTP error status, body read failure — errors 710-713) with the offending feed URL. It is surfaced to the user while configuring the datasource, so the whole validation fails on the first bad feed.

Source

Thrown at internal/datasource/connector/rss/connector.go:43

func NewConnector() *Connector { return &Connector{} }

// Type returns the connector type identifier.
func (c *Connector) Type() string { return types.ConnectorTypeRSS }

// Validate verifies that every configured feed URL is reachable and parses as
// a valid feed.
func (c *Connector) Validate(ctx context.Context, config *types.DataSourceConfig) error {
	cfg, err := parseConfig(config)
	if err != nil {
		return err
	}
	cli := newClient(cfg.parseHeaders())
	parser := gofeed.NewParser()

	for _, feedURL := range cfg.feedURLList() {
		data, err := cli.fetchFeed(ctx, feedURL)
		if err != nil {
			return fmt.Errorf("fetch feed %s: %w", feedURL, err)
		}
		if _, err := parser.Parse(bytes.NewReader(data)); err != nil {
			return fmt.Errorf("parse feed %s: %w", feedURL, err)
		}
	}
	return nil
}

// ResolveResourceAncestors has nothing to do: feeds are a flat list with no
// nesting, so a selection has no ancestors to reveal.
func (c *Connector) ResolveResourceAncestors(
	ctx context.Context, config *types.DataSourceConfig, resourceIDs []string,
) ([]string, error) {
	return []string{}, nil
}

// ListResources returns one resource per configured feed URL. The feed is
// fetched so the resource can carry its real title; a feed that fails to fetch

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Read the wrapped cause after the feed URL in the message: fix the specific root cause (URL typo, HTTP status, DNS) and re-validate.
  2. Verify the feed URL in a browser or with curl from the server running the connector — auth headers and network path differ from your workstation.
  3. If the URL is internal (private IP/localhost), the SSRF guard will block it; publish the feed on an address the SSRF policy allows.
  4. Split the feed list: validate each URL individually so one dead feed doesn't block a config with many good feeds.

Example fix

// before
feeds: ["https://blog.example/feed.xml", "htp://typo.example/rss"]
// after
feeds: ["https://blog.example/feed.xml", "https://good.example/rss.xml"]
Defensive patterns

Strategy: validation

Validate before calling

func preflightFeeds(ctx context.Context, urls []string) map[string]error {
    out := make(map[string]error, len(urls))
    for _, u := range urls {
        if err := validFeedURL(u); err != nil {
            out[u] = err
            continue
        }
        req, _ := http.NewRequestWithContext(ctx, http.MethodHead, u, nil)
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            out[u] = err
        } else if resp.StatusCode >= 400 {
            out[u] = fmt.Errorf("HTTP %d", resp.StatusCode)
        }
        resp.Body.Close()
    }
    return out
}

Try / catch

err := connector.Validate(ctx, cfg)
if err != nil {
    var uerr *url.Error
    if errors.As(err, &uerr) {
        return fmt.Errorf("feed configuration rejected, check URL/network for %s: %w", uerr.URL, uerr.Err)
    }
    return err
}

Prevention

When it happens

Trigger: During datasource configuration, any configured feed URL is unreachable: DNS failure, connection refused, TLS error, HTTP 4xx/5xx, URL rejected by SSRF validation (private/loopback address), malformed URL, or body read failure.

Common situations: Admin pastes a wrong or moved feed URL; feed host is down at validation time; internal/localhost feed URLs deliberately blocked by the SSRF guard; feeds requiring VPN access the server doesn't have; auth headers not yet configured for a token-gated feed.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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