google/tsunami-security-scanner · error · ParameterException
Malformed GCS URL
Error message
Malformed GCS URL: '%s'
What it means
ScanResultsArchiver.Options.validate() throws a picocli ParameterException when --gcs-output-file-url is set but does not match the expected Google Cloud Storage URL regex (GS_URL_PATTERN, e.g. gs://bucket/path). It guards against mistyped output destinations before the scan results archiving step runs.
Solutions
- Use the canonical form gs://<bucket>/<object-path> for --gcs-output-file-url.
- Remove surrounding whitespace or stray characters from the flag value.
- If you want local output instead, drop the GCS flag and use the local output directory option.
Example fix
// before --gcs-output-file-url=https://storage.googleapis.com/my-bucket/results.json // after --gcs-output-file-url=gs://my-bucket/results.json
Defensive patterns
Strategy: validation
Validate before calling
boolean ok = gcsUrl != null && !gcsUrl.isBlank() && gcsUrl.matches("^gs://[^/]+/.+"); Try / catch
try { archiverOptions.validate(); } catch (ParameterException e) { System.err.println("Fix --gcs-output-file-url: " + e.getMessage()); } Prevention
- Always use gs://bucket/object form for GCS outputs.
- Trim whitespace from flag values in wrapper scripts.
- Validate the URL in CI before running the scan.
When it happens
Trigger: Passing --gcs-output-file-url with a value like 'https://storage.googleapis.com/...' or 'gs:/bucket/x' that does not fully match GS_URL_PATTERN, checked in validate() at ScanResultsArchiver.java:73.
Common situations: Using an HTTP URL to a GCS object instead of the gs:// URI scheme; missing the bucket; extra whitespace; typos like 'gcs://' or a single slash after the scheme.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Remote plugin server port out of range. Expected
- Error loading config.
- One of the following parameters is expected…
- Language server path
- Port out of range. Expected
AI-assisted analysis of google/tsunami-security-scanner@363ba87b35 (2026-09-13).
Data as JSON: /api/errors/4941e069e562839f.
Report an issue: GitHub.
Appendix: source
Thrown at main/src/main/java/com/google/tsunami/main/cli/ScanResultsArchiver.java:73
description = "The GCS file url for the uploaded scanning results.")
public String gcsOutputFileUrl;
@Parameter(
names = "--scan-results-gcs-output-format",
description = "The format of the scanning results uploaded to GCS bucket.")
public OutputDataFormat gcsOutputFormat;
@Parameter(
names = "--scan-results-logging-enabled",
description = "Enable logging of the scan results.",
arity = 1)
public Boolean loggingEnabled = false;
@Override
public void validate() {
if (!Strings.isNullOrEmpty(gcsOutputFileUrl)
&& !GS_URL_PATTERN.matcher(gcsOutputFileUrl).matches()) {
throw new ParameterException(String.format("Malformed GCS URL: '%s'", gcsOutputFileUrl));
}
}
}
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private final Options options;
private final RawFileArchiver rawFileArchiver;
private final GoogleCloudStorageArchiver.Factory googleCloudStorageArchiverFactory;
@Inject
// TODO(b/145315535): inject archivers using multibinder instead.
ScanResultsArchiver(
Options options,
RawFileArchiver rawFileArchiver,
GoogleCloudStorageArchiver.Factory googleCloudStorageArchiverFactory) {
this.options = checkNotNull(options);
this.rawFileArchiver = checkNotNull(rawFileArchiver);View on GitHub (pinned to 363ba87b35)