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

  1. Retry the operation after a short delay — 5xx is usually transient on Notion's side.
  2. Check Notion's status page (status.notion.so) for an ongoing incident.
  3. Inspect the response body in the error message — a 502 HTML page indicates a proxy, not Notion itself.
  4. If a proxy is in the path, verify proxy health / timeouts and that baseURL is correct (ValidateConnectorBaseURL passed, but the upstream may be wrong).
  5. 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

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


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