Tencent/WeKnora · error
%w: %v
Error message
%w: %v
What it means
After the retry loop in doRequest exhausts all attempts without a 2xx or an immediate error return, the accumulated lastErr (rate limited / server error / transport error) is wrapped with the sentinel datasource.ErrFetchFailed using %w so callers can errors.Is() against it. If lastErr is somehow nil (loop ended without setting it), bare ErrFetchFailed is returned. This is the generic 'fetch ultimately failed' terminal error for all Notion API calls.
Source
Thrown at internal/datasource/connector/notion/client.go:149
continue
}
case resp.StatusCode >= 500:
lastErr = fmt.Errorf("server error %d: %s", resp.StatusCode, string(respBody))
if attempt < maxRetries {
if sErr := sleepWithContext(ctx, time.Duration(1<<attempt)*time.Second); sErr != nil {
return nil, sErr
}
continue
}
default:
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, string(respBody))
}
}
if lastErr != nil {
return nil, fmt.Errorf("%w: %v", datasource.ErrFetchFailed, lastErr)
}
return nil, datasource.ErrFetchFailed
}
// Ping verifies the API token is valid by calling GET /v1/users/me.
func (c *notionClient) Ping(ctx context.Context) error {
_, err := c.doRequest(ctx, http.MethodGet, "/v1/users/me", nil)
return err
}
// SearchPages returns all pages and databases accessible to the integration.
func (c *notionClient) SearchPages(ctx context.Context) ([]notionPage, error) {
return c.paginatePages(ctx, http.MethodPost, "/v1/search")
}
// GetPage retrieves a single page by ID.
func (c *notionClient) GetPage(ctx context.Context, pageID string) (*notionPage, error) {
respBody, err := c.doRequest(ctx, http.MethodGet, "/v1/pages/"+pageID, nil)View on GitHub (pinned to 988cbb0330)
Solutions
- Unwrap with errors.Is(err, datasource.ErrFetchFailed) then inspect the wrapped cause to distinguish rate-limit vs 5xx vs network failure.
- Verify network egress: curl https://api.notion.com/v1/users/me from the host to confirm connectivity and DNS.
- Check proxy env vars (HTTPS_PROXY) are correct if the host requires egress through a proxy.
- If persistent 429, reduce request volume or wait for the rate budget to reset.
- If persistent 5xx, check status.notion.so for an incident and retry the sync later.
Example fix
// before: opaque handling
if err != nil { return err }
// after: branch on the sentinel
if errors.Is(err, datasource.ErrFetchFailed) {
log.Printf("notion fetch failed permanently: %v", err)
// schedule retry / mark sync failed
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: confirm the token and network before long syncs
if err := client.Ping(ctx); err != nil {
return fmt.Errorf("notion pre-flight failed: %w", err)
} Try / catch
if errors.Is(err, datasource.ErrFetchFailed) {
switch {
case strings.Contains(err.Error(), "rate limited"):
// back off and reschedule
case strings.Contains(err.Error(), "server error"):
// retry later, likely Notion incident
default:
// network problem: check egress/proxy/DNS
}
} Prevention
- Always errors.Is() against datasource.ErrFetchFailed to identify terminal fetch failures
- Run a Ping pre-flight before bulk operations
- Confirm DNS/egress/proxy config on the deployment host
- Make sync jobs resumable so terminal failures don't restart from scratch
When it happens
Trigger: Any doRequest call where all 4 attempts fail identically: persistent 429s, persistent 5xx, or persistent transport errors (connection refused, DNS failure, timeouts) from Ping, GetPage, GetDatabaseInfo, GetDataSourceInfo, GetBlockChildrenFlat, or getBlockChildrenRecursive.
Common situations: Network egress blocked from the WeKnora host to api.notion.com (firewall, VPC without NAT); DNS resolution failures; Notion outage lasting longer than the ~7s retry window; ctx cancellation during backoff sleeps returns ctx.Err() instead, so this specifically fires for sustained failures.
Related errors
- server error %d: %s
- download file: %w
- invalid favorite resource type
- favorite resource id is required
- sandbox session no longer exists
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/62465e302fccada2.
Report an issue: GitHub.