apache/druid · error · IAE

Don't know how to load SCHEME [%s] for URI [%s]

Error message

Don't know how to load SCHEME [%s] for URI [%s]

What it means

HdfsDataSegmentPuller.getInputStream() only knows how to read segments stored on HDFS. When the URI's scheme is not 'hdfs' it refuses to proceed, throwing this IllegalArgumentException before touching the filesystem. It guards against misconfigured deep-storage URIs being handed to the HDFS puller.

Source

Thrown at extensions-core/hdfs-storage/src/main/java/org/apache/druid/storage/hdfs/HdfsDataSegmentPuller.java:317

    if (emitter == null) {
      return;
    }
    ServiceMetricEvent.Builder metricBuilder = ServiceMetricEvent.builder();
    metricBuilder.setDimension("format", format);
    emitter.emit(metricBuilder.setMetric("hdfs/pull/size", size));
    emitter.emit(metricBuilder.setMetric("hdfs/pull/duration", duration));
  }

  public InputStream getInputStream(Path path) throws IOException
  {
    return buildFileObject(path.toUri(), config).openInputStream();
  }

  @Override
  public InputStream getInputStream(URI uri) throws IOException
  {
    if (!uri.getScheme().equalsIgnoreCase(HdfsStorageDruidModule.SCHEME)) {
      throw new IAE("Don't know how to load SCHEME [%s] for URI [%s]", uri.getScheme(), uri.toString());
    }
    return buildFileObject(uri, config).openInputStream();
  }

  /**
   * Return the "version" (aka last modified timestamp) of the URI
   *
   * @param uri The URI of interest
   *
   * @return The last modified timestamp of the uri in String format
   *
   * @throws IOException
   */
  @Override
  public String getVersion(URI uri) throws IOException
  {
    try {
      return StringUtils.format("%d", buildFileObject(uri, config).getLastModified());

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Verify druid.storage.type is hdfs on all nodes that must pull these segments and that segments were actually pushed to HDFS
  2. Check the loadSpec URI in the segment metadata in the metadata store; it must start with hdfs://
  3. Ensure the hdfs-storage extension is the only active storage provider, or that deep storage is not mixed between S3/local and HDFS

Example fix

// before (URI from wrong storage)
URI uri = new URI("s3://bucket/segment/index.zip");
puller.getInputStream(uri); // throws
// after
URI uri = new URI("hdfs://namenode/druid/segments/.../index.zip");
puller.getInputStream(uri);
Defensive patterns

Strategy: validation

Validate before calling

if (!"hdfs".equalsIgnoreCase(uri.getScheme())) {
  throw new IllegalArgumentException("Expected hdfs:// URI, got: " + uri);
}
puller.getInputStream(uri);

Type guard

boolean isHdfsUri(java.net.URI uri) { return uri != null && "hdfs".equalsIgnoreCase(uri.getScheme()); }

Try / catch

try {
  in = puller.getInputStream(uri);
} catch (IllegalArgumentException e) {
  throw new IllegalStateException("Segment URI not on HDFS, check druid.storage.type/loadSpec: " + uri, e);
}

Prevention

When it happens

Trigger: Calling getInputStream(uri) with a URI whose scheme is not 'hdfs' (case-insensitive check fails), e.g. an 's3://', 'file://', or local-path segment URI routed to the HDFS puller.

Common situations: Deep storage misconfiguration: druid.storage.type=hdfs is loaded but historical nodes still resolve segment URIs written by another storage type (S3, local); mixing storage extensions on the same cluster; hand-written load specs pointing at the wrong scheme.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/7915854c917929bd. Report an issue: GitHub.