Tencent/WeKnora · error
server error %d: %s
Error message
server error %d: %s
What it means
The Notion API returned an HTTP 5xx server error. The client retries with exponential backoff (1s, 2s, 4s) up to maxRetries=3; this error escapes only when the server keeps failing across all attempts. It is then wrapped with datasource.ErrFetchFailed at client.go:149, so the surfaced error reads like `fetch failed: server error 502: ...` with the response body appended.
Source
Thrown at internal/datasource/connector/notion/client.go:135
return nil, fmt.Errorf("%w: %s", datasource.ErrResourceNotFound, path)
case resp.StatusCode == 429:
retryAfter := resp.Header.Get("Retry-After")
wait := 1 * time.Second
if secs, err := strconv.ParseFloat(retryAfter, 64); err == nil && secs > 0 {
wait = time.Duration(secs * float64(time.Second))
}
logger.Warnf(ctx, "[Notion] rate limited, retry after %v (attempt %d/%d)", wait, attempt+1, maxRetries)
lastErr = fmt.Errorf("rate limited: %s", string(respBody))
if attempt < maxRetries {
if sErr := sleepWithContext(ctx, wait); sErr != nil {
return nil, sErr
}
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
}
View on GitHub (pinned to 988cbb0330)
Solutions
- Retry the operation after a short delay — 5xx is usually transient on Notion's side.
- Check Notion's status page (status.notion.so) for an ongoing incident.
- Inspect the response body in the error message — a 502 HTML page indicates a proxy, not Notion itself.
- If a proxy is in the path, verify proxy health / timeouts and that baseURL is correct (ValidateConnectorBaseURL passed, but the upstream may be wrong).
- Increase maxRetries or backoff base in doRequest if your workload tolerates longer waits.
Example fix
// before
case resp.StatusCode >= 500:
lastErr = fmt.Errorf("server error %d: %s", resp.StatusCode, string(respBody))
// after (optional): treat 503 specially with a floor backoff
wait := time.Duration(1<<attempt) * time.Second
if resp.StatusCode == http.StatusServiceUnavailable { wait = 5 * time.Second } Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight connectivity check
resp, err := http.Get("https://status.notion.so")
// and verify egress: net.Dial("tcp", "api.notion.com:443") Try / catch
err := client.Ping(ctx)
if err != nil && strings.Contains(err.Error(), "server error") {
// transient 5xx: retry the whole operation after backoff
time.Sleep(time.Minute)
err = client.Ping(ctx)
} Prevention
- Subscribe to the Notion status page for incident alerts
- Retry syncs idempotently — the client already backs off 1/2/4s internally
- Avoid custom baseURL mirrors unless they are reliable
- Set generous HTTP timeouts (client uses 30s)
When it happens
Trigger: Any doRequest call (Ping, GetPage, GetDatabaseInfo, GetDataSourceInfo, GetBlockChildrenFlat, getBlockChildrenRecursive) where the response status is >= 500 on every attempt (0 through 3). Typical statuses: 500, 502, 503 from Notion or an intermediate proxy/gateway.
Common situations: Notion platform incidents or degraded service (check status.notion.so); corporate proxies / API gateways returning 502/504; custom baseURL pointing at a misbehaving mirror or self-hosted proxy; transient Notion overload during heavy load.
Related errors
- failed to generate questions: %w
- rate limited: %s
- %w: %v
- download failed with status %d
- download file: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/71e5c6af5bc7fb67.
Report an issue: GitHub.