{"record":{"id":"929eac651313331b","repo":"block/buzz","slug":"push-http-client","errorCode":null,"errorMessage":"push HTTP client","messagePattern":"push HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/push_runtime.rs","lineNumber":316,"sourceCode":"        return true;\n    }\n    let p = nostr::SingleLetterTag::lowercase(nostr::Alphabet::P);\n    filter.generic_tags.get(&p).is_some_and(|values| {\n        !values.is_empty()\n            && values.iter().all(|value| value == lease_author_hex)\n            && event\n                .tags\n                .filter(nostr::TagKind::SingleLetter(p))\n                .any(|tag| tag.content() == Some(lease_author_hex))\n    })\n}\n\n/// Continuously claim due wakes and deliver them through the push gateway.\npub async fn run_delivery_worker(state: Arc<AppState>) {\n    let http = reqwest::Client::builder()\n        .timeout(state.config.push_gateway_timeout)\n        .build()\n        .expect(\"push HTTP client\");\n    let mut idle_delay = Duration::from_millis(500);\n    loop {\n        let mut found = false;\n        match state.db.usage_community_hosts().await {\n            Ok(communities) => {\n                for community in communities {\n                    let community = buzz_core::CommunityId::from_uuid(community.id);\n                    let until = Utc::now() + TimeDelta::seconds(CLAIM_SECS);\n                    match state.db.claim_due_push_wakes(community, 16, until).await {\n                        Ok(wakes) => {\n                            for wake in wakes {\n                                found = true;\n                                deliver_one(&state, &http, wake).await;\n                            }\n                        }\n                        Err(e) => warn!(%community, \"push wake claim failed: {e}\"),\n                    }\n                }","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/block/buzz/blob/934f3325c3fdaa3a6f23134b74518139aac8ca3f/crates/buzz-relay/src/push_runtime.rs#L298-L334","documentation":"run_delivery_worker builds one reqwest::Client (with push_gateway_timeout) for all push-gateway deliveries. Client::build() almost never fails; the realistic failure is TLS-backend initialization (e.g. native-tls/OpenSSL context creation) failing in the process environment. The expect panics, so the push delivery worker task dies at startup and no pushes are ever delivered.","triggerScenarios":"reqwest compiled with native-tls on a host where OpenSSL fails to initialize (missing or incompatible shared libraries); minimal container images lacking the TLS backend's runtime prerequisites.","commonSituations":"Distroless/alpine images without a compatible OpenSSL; host OpenSSL upgrades after the binary was built; CI runners with restrictive syscall filters.","solutions":["Build reqwest with the rustls TLS backend (features = [\"rustls-tls\"]) so no system OpenSSL is needed — consistent with the ring provider the relay already installs","Verify the TLS libraries the binary links (ldd) exist and match inside the runtime image","Propagate the build error instead of expect so a dead push worker surfaces as an observable startup failure"],"exampleFix":"// before\nlet http = reqwest::Client::builder()\n    .timeout(state.config.push_gateway_timeout)\n    .build()\n    .expect(\"push HTTP client\");\n\n// after\nlet http = reqwest::Client::builder()\n    .timeout(state.config.push_gateway_timeout)\n    .build()\n    .map_err(|e| {\n        tracing::error!(\"push worker: HTTP client build failed: {e}\");\n        e\n    })?; // make run_delivery_worker return Result and report at spawn site","handlingStrategy":"validation","validationCode":"// startup preflight before spawning the push worker\nlet probe = reqwest::Client::builder().build();\nif probe.is_err() {\n    return Err(anyhow!(\"push worker: reqwest client cannot initialize (TLS backend problem)\"));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build reqwest with the rustls TLS backend so client construction has no system-OpenSSL dependency","Include CA certificates and required TLS libraries in minimal runtime images","Make long-lived worker tasks report init failures observably (metric/log line) instead of panicking silently in the dark"],"tags":["rust","reqwest","tls","push-notifications","startup","worker"],"backgroundTag":"http-client-init-failed","analyzedSha":"934f3325c3fdaa3a6f23134b74518139aac8ca3f","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}