{"record":{"id":"f01e91299ba11b83","repo":"Hmbown/CodeWhale","slug":"build-platform-http-client-f01e91","errorCode":null,"errorMessage":"build platform HTTP client","messagePattern":"build platform HTTP client","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/install.rs","lineNumber":56,"sourceCode":"//!   does not execute `plugin.json` plugin runtimes or custom command bundles.\n\nuse std::fs;\nuse std::io::{Read, Write};\nuse std::path::{Component, Path, PathBuf};\n\nuse anyhow::{Context, Result, bail};\nuse flate2::read::GzDecoder;\nuse futures_util::stream::{self, StreamExt};\nuse serde::{Deserialize, Serialize};\nuse sha2::{Digest, Sha256};\nuse thiserror::Error;\n\nuse crate::network_policy::{Decision, NetworkPolicy, host_from_url};\n\nfn reqwest_client() -> reqwest::Client {\n    codewhale_release::platform_http_client_builder()\n        .build()\n        .expect(\"build platform HTTP client\")\n}\n\n/// Cache directory for registry-synced skills.\n///\n/// Lives at `~/.codewhale/cache/skills/` so it's separate from user-installed\n/// skills and can be blown away without losing anything irreplaceable.\npub fn default_cache_skills_dir() -> PathBuf {\n    crate::config::effective_home_dir().map_or_else(\n        || PathBuf::from(\"/tmp/codewhale/cache/skills\"),\n        |p| p.join(\".codewhale\").join(\"cache\").join(\"skills\"),\n    )\n}\n\n/// Default registry. Falls back to a community-curated `index.json` hosted on\n/// GitHub raw; users can override via `[skills] registry_url` in config.toml.\npub const DEFAULT_REGISTRY_URL: &str =\n    \"https://raw.githubusercontent.com/Hmbown/deepseek-skills/main/index.json\";\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/skills/install.rs#L38-L74","documentation":"Panic building the HTTP client used for registry-synced skill installs. `codewhale_release::platform_http_client_builder().build()` fails when the TLS stack cannot initialize — typically a rustls-native-certs failure reading `SSL_CERT_FILE`/`SSL_CERT_DIR` (set to a nonexistent path), an unreadable system CA bundle, or a broken OpenSSL for native-tls builds. The expect fires on the first network-touching skills operation.","triggerScenarios":"Environment with `SSL_CERT_FILE` or `SSL_CERT_DIR` exported to a missing file (common in hardened shells, Nix, direnv); empty or unreadable `/etc/ssl/certs`; corporate MITM proxy roots installed only in a nonstandard store. Any skill install/sync then panics inside `reqwest_client()` (skills/install.rs:56).","commonSituations":"CI images without `ca-certificates`; dev containers where the env var leaks from another tool; dotfiles copied between macOS and Linux machines; air-gapped hosts with modified cert layouts.","solutions":["Check the environment: `env | grep -iE 'ssl|proxy'` and verify `SSL_CERT_FILE`/`SSL_CERT_DIR` point at existing, readable files; unset them if stale.","Install or refresh the system CA bundle (`apt-get install --reinstall ca-certificates` or the platform equivalent) and retry the skill install.","Behind a TLS-intercepting proxy, point `SSL_CERT_FILE` at the corporate root bundle.","If it persists, reproduce with `RUST_BACKTRACE=1` to confirm the failure is inside the platform client builder and report the builder configuration."],"exampleFix":"// before\ncodewhale_release::platform_http_client_builder().build().expect(\"build platform HTTP client\")\n\n// after: build lazily and return the error to the install flow\nfn reqwest_client() -> std::result::Result<reqwest::Client, reqwest::Error> {\n    codewhale_release::platform_http_client_builder().build()\n}","handlingStrategy":"validation","validationCode":"// Check the TLS environment before the first skills network call\nfor var in [\"SSL_CERT_FILE\", \"SSL_CERT_DIR\"] {\n    if let Ok(v) = std::env::var(var) {\n        assert!(std::path::Path::new(&v).exists(), \"{var}={v} does not exist\");\n    }\n}","typeGuard":null,"tryCatchPattern":"let client = std::panic::catch_unwind(reqwest_client)\n    .unwrap_or_else(|_| reqwest::Client::new()); // default client without native-cert customization","preventionTips":["Keep `ca-certificates` installed in CI and dev images.","Audit SSL_* env vars when moving dotfiles between machines or entering Nix/direnv shells.","Behind a TLS-intercepting proxy, point SSL_CERT_FILE at the corporate root bundle."],"tags":["rust","reqwest","tls","ca-certificate","skills-install","panic","expect"],"backgroundTag":"http-client-build-failed","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}