apache/beam · error · RuntimeException

Unable to create URI for GCS path

Error message

Unable to create URI for GCS path %s

What it means

GcsPath.toUri() builds a hierarchical URI of the form gs://bucket/object via new URI(SCHEME, "//" + bucketAndObject(), null). If the bucket/object contains characters that are illegal in a URI (e.g. spaces, unencoded special characters), URISyntaxException is caught and rethrown as a RuntimeException.

Solutions

  1. Rename/sanitize the GCS object to contain URI-safe characters
  2. Percent-encode the object name before creating the GcsPath (e.g. URLEncoder on path segments)
  3. Catch the RuntimeException at the call site and skip/handle such objects

Example fix

// before
URI uri = new URI("gs", "//" + bucket + "/" + object, null);
// after
String enc = java.net.URLEncoder.encode(object, StandardCharsets.UTF_8)
    .replace("+", "%20");
URI uri = new URI("gs", "//" + bucket + "/" + enc, null);
Defensive patterns

Strategy: try-catch

Validate before calling

new java.net.URI("gs", "//" + path.getBucket() + "/" + path.getObject(), null); // pre-validate

Try / catch

try { URI uri = path.toUri(); } catch (RuntimeException e) { if (e.getMessage().startsWith("Unable to create URI")) { /* sanitize object name or skip */ } else throw e; }

Prevention

When it happens

Trigger: Calling toUri() on a GcsPath whose bucket or object name contains characters invalid for URIs, such as raw spaces, '#', or other reserved characters that the multi-argument URI constructor rejects in that component.

Common situations: Objects uploaded by other tools with unencoded filenames (spaces, unicode punctuation) then processed through Beam's GCS filesystem; constructing URIs for logging or comparison.

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.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/630ee92b3c05a589. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/util/gcsfs/GcsPath.java:600

  }

  // TODO: Consider using resource names for all GCS paths used by the SDK.
  public String toResourceName() {
    StringBuilder sb = new StringBuilder();
    sb.append("storage.googleapis.com/");
    if (!bucket.isEmpty()) {
      sb.append(bucket).append('/');
    }
    sb.append(object);
    return sb.toString();
  }

  @Override
  public URI toUri() {
    try {
      return new URI(SCHEME, "//" + bucketAndObject(), null);
    } catch (URISyntaxException e) {
      throw new RuntimeException("Unable to create URI for GCS path " + this);
    }
  }

  private String bucketAndObject() {
    if (bucket.isEmpty()) {
      return object;
    } else {
      return bucket + "/" + object;
    }
  }

  /** Returns the prefix portion of the glob before the first wildcard character. */
  public static String getNonWildcardPrefix(String globExp) {
    Matcher m = GLOB_PREFIX.matcher(globExp);
    checkArgument(m.matches(), String.format("Glob expression: [%s] is not expandable.", globExp));
    return m.group("PREFIX");
  }

View on GitHub (pinned to 12126d8942)