jdx/mise · error · eyre::Report
URL must use s3:// scheme, got: {}
Error message
URL must use s3:// scheme, got: {} What it means
The s3:// backend parses tool URLs with S3Url::parse, which accepts only the `s3://bucket/key` form. Any URL whose scheme is not `s3` (typically `https://` or `http://`) is rejected before any download starts.
Source
Thrown at src/backend/s3.rs:77
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tokio::sync::OnceCell;
use url::Url;
/// Parsed S3 URL components
#[derive(Debug, Clone)]
struct S3Url {
bucket: String,
key: String,
}
impl S3Url {
/// Parse an S3 URL like "s3://bucket/path/to/object?region=us-west-2"
fn parse(url_str: &str) -> Result<Self> {
let url = Url::parse(url_str).map_err(|e| eyre!("Invalid S3 URL: {e}"))?;
if url.scheme() != "s3" {
bail!("URL must use s3:// scheme, got: {}", url.scheme());
}
let bucket = url
.host_str()
.ok_or_else(|| eyre!("S3 URL must include bucket name"))?
.to_string();
if bucket.is_empty() {
bail!("S3 URL must include bucket name");
}
let key = url.path().trim_start_matches('/').to_string();
Ok(Self { bucket, key })
}
}
/// S3 backend for downloading tools from Amazon S3 or S3-compatible storageView on GitHub (pinned to 6f52dcdf99)
Solutions
- Rewrite the URL as `s3://bucket/key.tar.gz` (path only, no scheme-specific host)
- If the asset is only reachable over HTTPS, use the http backend (`http://bucket/key.tar.gz`) or aqua/github instead of s3
- Verify the scheme string has no leading whitespace or smart characters
Example fix
# before [tools.foo] version = "1.0.0" backend = "s3" url = "https://my-bucket.s3.amazonaws.com/foo-1.0.0.tar.gz" # after [tools.foo] version = "1.0.0" backend = "s3" url = "s3://my-bucket/foo-1.0.0.tar.gz"
Defensive patterns
Strategy: validation
Validate before calling
# Validate before install
python3 - <<'EOF'
from urllib.parse import urlparse
u = urlparse(open('mise.toml').read()) # or parse your url value
assert urlparse('s3://bucket/key').scheme == 's3'
EOF
# simpler: grep the url lines
! grep -n 'url[[:space:]]*=[[:space:]]*"https\?://' mise.toml Type guard
fn is_s3_url(s: &str) -> bool {
url::Url::parse(s).map(|u| u.scheme() == "s3").unwrap_or(false)
} Prevention
- Use s3://bucket/key form for the s3 backend; use the http backend for plain URLs
- Script a config lint that checks backend/url scheme pairs in mise.toml
- Prefer aqua: shorthand when the tool is in the aqua registry
When it happens
Trigger: Declaring a tool with `backend = "s3"` (or `s3:` shorthand) but setting `url = "https://bucket.s3.amazonaws.com/key.tar.gz"`. Also triggered by a typo like `s4://` or an empty url that happens to parse with a different default scheme.
Common situations: Copying a presigned or public HTTPS S3 link from the AWS console into mise.toml, or migrating an http backend entry to s3 by editing only the host part.
Related errors
- S3 URL must include bucket name
- artifactbundle must be true, false, 1, or 0, got {value}
- install_command must be a non-empty string
- install_command cannot be used with filter_bins
- artifactbundle_asset must end with .artifactbundle.zip, got
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/3d97609ad659d2c4.
Report an issue: GitHub.