xai-org/grok-build · error
Invalid GCS URL scheme: expected 'gs', got '{}'
Error message
Invalid GCS URL scheme: expected 'gs', got '{}' What it means
upload_bytes (used by upload_bytes_signed) parses the configured bucket_url as a URL and requires the scheme to be 'gs' for direct (non-HTTP) GCS access. If the scheme is anything else (https, s3, or a typo), it bails with this message naming the offending scheme. This guards against misconfigured storage endpoints being handed to the GCS-specific code path.
Source
Thrown at crates/codegen/xai-file-utils/src/gcs.rs:116
/// Uploads bytes to cloud storage at the specified path.
/// Returns the full storage URL on success.
/// Dispatches to direct, proxy, or S3 backend based on config.
pub async fn upload_bytes<C: StorageConfig>(
config: &C,
object_path: &str,
content: &[u8],
content_type: &str,
) -> anyhow::Result<String> {
match config.upload_method() {
UploadMethod::Direct {
service_account_key,
} => {
// Parse the bucket URL to extract bucket name (required for direct mode)
let url = url::Url::parse(config.bucket_url())
.with_context(|| format!("Invalid GCS URL: {}", config.bucket_url()))?;
if url.scheme() != "gs" {
anyhow::bail!(
"Invalid GCS URL scheme: expected 'gs', got '{}'",
url.scheme()
);
}
let bucket = url
.host_str()
.context("GCS URL must have a bucket name")?
.to_string();
upload_bytes_direct(
&bucket,
object_path,
content,
content_type,
service_account_key.as_deref(),
)
.awaitView on GitHub (pinned to bc7f02eddd)
Solutions
- Set bucket_url to a proper gs:// URL, e.g. gs://my-bucket (optionally with object prefix).
- Check the env var/config source feeding bucket_url for typos (gcs://, GS://) — the scheme is compared case-sensitively after URL parsing.
- If you have an HTTPS endpoint intentionally (emulator/proxy), use the non-direct upload mode instead of the direct gs:// path.
- Validate the URL at startup (parse and assert scheme == "gs") so failures surface in config checks, not mid-upload.
Example fix
// before
let config = GcsConfig { bucket_url: "https://storage.googleapis.com/my-bucket".into(), .. };
upload_bytes(&config, key, data).await?;
// after
let config = GcsConfig { bucket_url: "gs://my-bucket".into(), .. };
upload_bytes(&config, key, data).await?; Defensive patterns
Strategy: validation
Validate before calling
fn validate_gcs_bucket_url(bucket_url: &str) -> Result<(), String> {
let url = url::Url::parse(bucket_url).map_err(|e| format!("bad URL: {e}"))?;
if url.scheme() != "gs" {
return Err(format!("scheme must be 'gs', got '{}' in {bucket_url}", url.scheme()));
}
if url.host_str().unwrap_or_default().is_empty() {
return Err("missing bucket name".into());
}
Ok(())
}
validate_gcs_bucket_url(config.bucket_url())?; // run at startup, not mid-upload Try / catch
match upload_bytes(&config, key, data).await {
Err(e) if e.to_string().contains("Invalid GCS URL scheme") => {
return Err(anyhow::anyhow!(
"config error: bucket_url={} must be a gs:// URL",
config.bucket_url()
));
}
other => other,
} Prevention
- Store bucket as a bare name (my-bucket) and construct gs:// at call time
- Validate bucket_url scheme at config load/startup
- Never paste https:// signed URLs into bucket_url config
- Keep per-provider config types separate so S3 URLs can't reach GCS paths
- Watch env-var substitution — empty vars yield schemeless URLs
When it happens
Trigger: Calling upload_bytes/upload_bytes_signed with a config whose bucket_url() is set to an https:// URL, an s3:// URL, a bare hostname, or a misspelled scheme (gcs://, GS://).
Common situations: Copy-pasting a signed HTTPS console URL into bucket_url config; reusing an S3-style config struct for GCS; environment-variable substitution producing an empty or wrong-prefixed URL; docs examples mixing cloud providers.
Related errors
- no CLI base URLs to try
- no CLI base URLs configured
- Writeback storage mode requires authentication. Run 'grok lo
- no target specified
- {LOCAL_WORKSPACE_REQUIRES_CHAT}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/bc1986fa67f35603.
Report an issue: GitHub.