Hmbown/CodeWhale · error

outbound origin must use https

Error message

outbound origin must use https

What it means

The final check in validate_outbound_origin requires https for every origin that got this far. http is only tolerated for loopback hosts in debug builds; all public hosts must use TLS because these URLs carry credentials.

Solutions

  1. Change the origin scheme to https:// and ensure the service terminates TLS.
  2. Put the service behind a TLS-terminating proxy (nginx/Caddy/cloud LB) and use that URL.
  3. Verify the exact env var/config value — an http:// default may need overriding.

Example fix

// before
export DAYTONA_API_URL=http://api.example.com
// after
export DAYTONA_API_URL=https://api.example.com
Defensive patterns

Strategy: validation

Validate before calling

if raw.trim().starts_with("http://") { return Err("use https:// for remote origins"); }

Try / catch

match validate_outbound_origin(raw) {
    Err(e) if e.to_string().contains("must use https") => eprintln!("enable TLS or put a TLS proxy in front: {raw}"),
    other => other?,
}

Prevention

When it happens

Trigger: Passing an http:// public URL (e.g. http://api.example.com) as the remote endpoint or toolbox URL after it passed the scheme/host checks.

Common situations: Self-hosted services fronted only by plain http; miswritten config dropping the 's'; legacy internal endpoints exposed via http proxy.

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 Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/8d14cfaf8e7ffa37. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/cloud_dispatch.rs:1330

                        || v4.is_broadcast()
                        || v4.is_multicast()
                        || v4.is_documentation()
                        || (octets[0] == 100 && (octets[1] & 0b1100_0000) == 0b0100_0000)
                } else {
                    v6.is_loopback()
                        || v6.is_unspecified()
                        || v6.is_multicast()
                        || (v6.segments()[0] & 0xfe00) == 0xfc00
                        || (v6.segments()[0] & 0xffc0) == 0xfe80
                }
            }
        };
        if blocked {
            bail!("outbound origin must not target a loopback, private, or reserved address");
        }
    }
    if url.scheme() != "https" {
        bail!("outbound origin must use https");
    }
    Ok(url)
}

/// Meter one closed interval on a dispatched cloud job.
///
/// The job's sandbox id must match the provider observation. Wall-clock after
/// create is not enough: the observation has to be provider-accepted active
/// time bound to the immutable admission.
pub fn meter_cloud_job(
    job: &CloudJob,
    admission: &ComputerAdmission,
    observation: ProviderObservation,
) -> Result<ComputerMeterReceipt, ComputerMeterError> {
    match job.sandbox_id.as_deref() {
        Some(sandbox_id) if sandbox_id == observation.provider_sandbox_id => {
            issue_computer_meter_receipt(admission, observation)
        }

View on GitHub (pinned to 73e0f67d83)