{"record":{"id":"98d7303e854fdfcf","repo":"dbt-labs/dbt-core","slug":"download-base-url-must-be-an-https-url-got-base","errorCode":null,"errorMessage":"download base url must be an https URL, got {base_url:?}","messagePattern":"download base url must be an https URL, got (.+?)","errorType":"validation","errorClass":"anyhow","httpStatus":null,"severity":"error","filePath":"crates/dbt-ci/src/utils.rs","lineNumber":18,"sourceCode":"use anyhow::{Result, bail};\nuse sha2::{Digest, Sha256};\nuse std::env;\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::time::Duration;\nuse toml_edit::DocumentMut;\n\n/// Lowercase hex sha256 of `data`; the one hashing form shared across the crate.\npub(crate) fn sha256_hex(data: &[u8]) -> String {\n    hex::encode(Sha256::digest(data))\n}\n\n/// Rejects a download base url that isn't `https://`, so wheels are never\n/// fetched over an insecure transport.\npub(crate) fn require_https(base_url: &str) -> Result<()> {\n    if !base_url.starts_with(\"https://\") {\n        bail!(\"download base url must be an https URL, got {base_url:?}\");\n    }\n    Ok(())\n}\n\n/// Retry only on errors that may heal: timeouts, connect failures, body blips.\n/// `is_request()` (builder/config errors) is excluded — it won't change on retry.\npub(crate) fn is_transient(e: &reqwest::Error) -> bool {\n    e.is_timeout() || e.is_connect() || e.is_body()\n}\n\n/// Exponential backoff between HTTP retries: 500ms, 1s, 2s, 4s, …\npub(crate) fn backoff(attempt: u32) -> Duration {\n    Duration::from_millis(500u64 * (1u64 << (attempt - 1)))\n}\n\n/// Nearest ancestor of `CARGO_MANIFEST_DIR` whose `Cargo.toml` has a\n/// `[workspace]` table. Falls back to cwd (then `.`) if no ancestor matches.\npub(crate) fn cargo_workspace_root() -> PathBuf {","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-ci/src/utils.rs#L1-L36","documentation":"This error is thrown by `require_https` in crates/dbt-ci/src/utils.rs when a download base URL does not start with the `https://` scheme. The library enforces TLS-secured transports so release artifacts (wheels/sdists) are never fetched or published over plaintext HTTP, which would expose downloads to tampering and MITM attacks. It is a fail-fast guard called by `build_sdist` and `build_release_sdist` before any network activity.","triggerScenarios":"Calling `build_sdist` or `build_release_sdist` with a base URL configured as `http://...`, a schemeless host like `example.com/download`, or an `ftp://`/other non-https URL. Any string that fails `base_url.starts_with(\"https://\")` triggers the bail.","commonSituations":"A CI config or env var pointing at an internal HTTP mirror; someone pasting a URL without the scheme; switching from a local dev server (`http://localhost`) to production and forgetting to update the scheme; typoed URLs like `https:/host` (single slash).","solutions":["Change the configured base URL to use the `https://` scheme (e.g. `https://github.com/org/repo/releases/download`).","If targeting a local/dev endpoint, run it behind a local TLS proxy or use an https-capable local server.","Verify the value comes from the right env var/config key and contains no leading whitespace or typos (e.g. `https:/` with one slash)."],"exampleFix":"// before\nlet base_url = \"http://internal-mirror.example.com/download\";\nbuild_release_sdist(base_url)?;\n// after\nlet base_url = \"https://internal-mirror.example.com/download\";\nbuild_release_sdist(base_url)?;","handlingStrategy":"validation","validationCode":"if !base_url.starts_with(\"https://\") {\n    return Err(format!(\"download base url must be https, got {base_url:?}\"));\n}","typeGuard":"fn is_https_url(url: &str) -> bool {\n    url::Url::parse(url).map(|u| u.scheme() == \"https\").unwrap_or(false)\n}","tryCatchPattern":"match build_release_sdist(base_url) {\n    Err(e) if e.to_string().contains(\"https URL\") => eprintln!(\"fix the base URL scheme: {e}\"),\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Store download URLs with the https:// scheme in config from day one.","Validate scheme at config-load time, not at request time.","Use a typed URL wrapper (e.g. parse with the `url` crate) instead of raw strings.","Reject http:// explicitly in CI lint checks for release configs."],"tags":["https","url-validation","security","release-pipeline"],"backgroundTag":"invalid-url","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}