{"record":{"id":"a377d109506c5723","repo":"netdata/netdata","slug":"name-http","errorCode":null,"errorMessage":"{name} HTTP {}","messagePattern":"\\{name\\} HTTP \\{\\}","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crates/otel-streams/src/sse.rs","lineNumber":99,"sourceCode":"/// to stop (typically because the downstream channel closed). Returns `Ok` on\n/// stream end or a read error so the caller's reconnect loop takes over.\npub async fn run<H, F>(name: &str, url: &str, mut handler: H) -> anyhow::Result<()>\nwhere\n    H: FnMut(serde_json::Value) -> F + Send + 'static,\n    F: Future<Output = ControlFlow<(), ()>> + Send,\n{\n    info!(\"Connecting to {name}: {url}\");\n\n    let client = reqwest::Client::new();\n    let response = client\n        .get(url)\n        .header(reqwest::header::USER_AGENT, USER_AGENT)\n        .header(reqwest::header::ACCEPT, \"text/event-stream\")\n        .send()\n        .await?;\n\n    if !response.status().is_success() {\n        anyhow::bail!(\"{name} HTTP {}\", response.status());\n    }\n    info!(\"Connected to {name}\");\n\n    let mut stream = response.bytes_stream();\n    let mut decoder = SseDecoder::default();\n\n    while let Some(chunk) = stream.next().await {\n        let chunk = match chunk {\n            Ok(c) => c,\n            Err(e) => {\n                error!(\"{name} SSE stream error: {e}\");\n                break;\n            }\n        };\n\n        for raw in decoder.push(&chunk) {\n            let value: serde_json::Value = match serde_json::from_str(&raw) {\n                Ok(v) => v,","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/netdata/netdata/blob/4864de85e26f6734d92cfc27ccbeff5921f49938/src/crates/otel-streams/src/sse.rs#L81-L117","documentation":"otel-streams' SSE connector issues a GET with Accept: text/event-stream and treats any non-2xx response status as fatal, bailing with the source name and HTTP status (e.g. 'GitHub Events HTTP 403'). The message uses a runtime format on response.status(), so the logged text is the status line. A successful connect is logged before the byte-stream loop begins; this error is purely about the initial HTTP response.","triggerScenarios":"The SSE URL returns 401/403 (bad or expired token), 404 (wrong endpoint path), 429 (rate limited), or 5xx (upstream outage) when the connector connects.","commonSituations":"Expired GitHub tokens or hitting API rate limits on the events stream; typos in the stream URL; proxy or corporate gateways rejecting the long-lived connection; upstream maintenance windows.","solutions":["Check the status in the message: 401/403 → refresh/fix credentials; 404 → verify the URL; 429 → back off and respect rate limits","Confirm any required auth headers/tokens are still valid for the SSE source","Retry with exponential backoff for transient 5xx/429; treat 4xx (other than 429) as config errors, not retriable"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"# smoke-check the stream URL and auth before the long-running connector\ncurl -sS -o /dev/null -w '%{http_code}\\n' -H 'Accept: text/event-stream' \"$SSE_URL\" # expect 200","typeGuard":null,"tryCatchPattern":"in the caller, catch the error, parse the trailing HTTP status: 429/5xx → backoff-and-retry with jitter; 401/403 → halt and refresh credentials; 404 → halt and fix the URL","preventionTips":["Rotate SSE source tokens before expiry and monitor rate-limit headers","Pre-flight the URL with curl in deployment checks so config errors surface at deploy time"],"tags":["http","sse","streaming","network","otel","streams","github"],"backgroundTag":null,"analyzedSha":"4864de85e26f6734d92cfc27ccbeff5921f49938","analyzedAt":"2026-08-15T09:12:38.226Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}