dbt-labs/dbt-core · error · anyhow
download base url must be an https URL, got {base_url:?}
Error message
download base url must be an https URL, got {base_url:?} What it means
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.
Source
Thrown at crates/dbt-ci/src/utils.rs:18
use anyhow::{Result, bail};
use sha2::{Digest, Sha256};
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::time::Duration;
use toml_edit::DocumentMut;
/// Lowercase hex sha256 of `data`; the one hashing form shared across the crate.
pub(crate) fn sha256_hex(data: &[u8]) -> String {
hex::encode(Sha256::digest(data))
}
/// Rejects a download base url that isn't `https://`, so wheels are never
/// fetched over an insecure transport.
pub(crate) fn require_https(base_url: &str) -> Result<()> {
if !base_url.starts_with("https://") {
bail!("download base url must be an https URL, got {base_url:?}");
}
Ok(())
}
/// Retry only on errors that may heal: timeouts, connect failures, body blips.
/// `is_request()` (builder/config errors) is excluded — it won't change on retry.
pub(crate) fn is_transient(e: &reqwest::Error) -> bool {
e.is_timeout() || e.is_connect() || e.is_body()
}
/// Exponential backoff between HTTP retries: 500ms, 1s, 2s, 4s, …
pub(crate) fn backoff(attempt: u32) -> Duration {
Duration::from_millis(500u64 * (1u64 << (attempt - 1)))
}
/// Nearest ancestor of `CARGO_MANIFEST_DIR` whose `Cargo.toml` has a
/// `[workspace]` table. Falls back to cwd (then `.`) if no ancestor matches.
pub(crate) fn cargo_workspace_root() -> PathBuf {View on GitHub (pinned to 0267ce9170)
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).
Example fix
// before let base_url = "http://internal-mirror.example.com/download"; build_release_sdist(base_url)?; // after let base_url = "https://internal-mirror.example.com/download"; build_release_sdist(base_url)?;
Defensive patterns
Strategy: validation
Validate before calling
if !base_url.starts_with("https://") {
return Err(format!("download base url must be https, got {base_url:?}"));
} Type guard
fn is_https_url(url: &str) -> bool {
url::Url::parse(url).map(|u| u.scheme() == "https").unwrap_or(false)
} Try / catch
match build_release_sdist(base_url) {
Err(e) if e.to_string().contains("https URL") => eprintln!("fix the base URL scheme: {e}"),
Err(e) => return Err(e),
Ok(v) => v,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/98d7303e854fdfcf.
Report an issue: GitHub.