apache/hadoop · error · IllegalArgumentException

GCS path must include non-empty object name [objectName='%s'

Error message

GCS path must include non-empty object name [objectName='%s', allowEmptyObjectName=%s]

What it means

StringPaths.validateObjectName with allowEmptyObjectName=false requires a non-empty object name that is not just '/'. fromUriPath passes false whenever a concrete storage object is expected, so bucket-root URIs like gs://bucket or gs://bucket/ are rejected with IllegalArgumentException naming the objectName and the flag.

Source

Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/StringPaths.java:87

  /**
   * Validate the given object name to make sure that it can be used as a part of a file system
   * path.
   *
   * <p>Note: this is not designed to duplicate the exact checks that GCS would perform on the
   * server side. We make some checks that are relevant to using GCS as a file system.
   *
   * @param objectName           Object name to check.
   * @param allowEmptyObjectName If true, a missing object name is not considered invalid.
   */
  static String validateObjectName(String objectName, boolean allowEmptyObjectName) {
    LOG.trace("validateObjectName('{}', {})", objectName, allowEmptyObjectName);

    if (isNullOrEmpty(objectName) || objectName.equals(PATH_DELIMITER)) {
      if (allowEmptyObjectName) {
        objectName = "";
      } else {
        throw new IllegalArgumentException(String.format(
            "GCS path must include non-empty object name [objectName='%s',"
                + " allowEmptyObjectName=%s]", objectName, allowEmptyObjectName));
      }
    }

    // We want objectName to look like a traditional file system path,
    // therefore, disallow objectName with consecutive '/' chars.
    for (int i = 0; i < (objectName.length() - 1); i++) {
      if (objectName.charAt(i) == '/' && objectName.charAt(i + 1) == '/') {
        throw new IllegalArgumentException(
            String.format("GCS path must not have consecutive '/' characters: '%s'", objectName));
      }
    }

    // Remove leading '/' if it exists.
    if (objectName.startsWith(PATH_DELIMITER)) {
      objectName = objectName.substring(1);
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Append a concrete object name: gs://bucket/dir/file.txt.
  2. Only pass allowEmptyObjectName=true where a directory/root path is acceptable (as listDirectory does).
  3. Validate that the computed filename is non-empty before constructing the URI.

Example fix

// before
StorageResourceId.fromUriPath(URI.create("gs://bucket"), false);
// -> IllegalArgumentException: must include non-empty object name

// after
StorageResourceId.fromUriPath(URI.create("gs://bucket/file.txt"), false);
Defensive patterns

Strategy: validation

Validate before calling

String object = computedObjectName();
if (object == null || object.isEmpty() || object.equals("/")) {
  throw new IllegalArgumentException("Object name required for file operations");
}
URI uri = URI.create("gs://" + bucket + "/" + object);
StorageResourceId id = StorageResourceId.fromUriPath(uri, false);

Type guard

static boolean hasObjectName(URI u) {
  String p = u.getPath();
  return p != null && !p.isEmpty() && !p.equals("/");
}

Try / catch

catch IllegalArgumentException with message contains("must include non-empty object name") - append the intended object name to the URI, or switch to an API/context that permits directory paths (allowEmptyObjectName=true).

Prevention

When it happens

Trigger: fromUriPath(URI.create("gs://bucket"), false) or 'gs://bucket/'; open/create on a bucket root; filenames computed as empty by path logic (e.g. substring after the last '/' when there is none).

Common situations: Treating the bucket root as a file path; empty filename from string operations or user input; directory-vs-file confusion where a directory URI (which legitimately has an empty object name) is fed to an API requiring an object.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/d37f98d6c59939e8. Report an issue: GitHub.