{"record":{"id":"6f1d6a53c672be87","repo":"apache/druid","slug":"ioexception-wrapping-underlying-cause-6f1d6a","errorCode":null,"errorMessage":"IOException wrapping underlying cause","messagePattern":"IOException wrapping underlying cause","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"extensions-core/azure-extensions/src/main/java/org/apache/druid/storage/azure/output/AzureStorageConnector.java","lineNumber":68,"sourceCode":"  private final AzureStorage azureStorage;\n\n  public AzureStorageConnector(\n      final AzureOutputConfig config,\n      final AzureStorage azureStorage\n  )\n  {\n    this.config = config;\n    this.azureStorage = azureStorage;\n  }\n\n  @Override\n  public ChunkingStorageConnectorParameters<AzureInputRange> buildInputParams(String path) throws IOException\n  {\n    try {\n      return buildInputParams(path, 0, azureStorage.getBlockBlobLength(config.getContainer(), objectPath(path)));\n    }\n    catch (BlobStorageException e) {\n      throw new IOException(e);\n    }\n  }\n\n  @Override\n  public ChunkingStorageConnectorParameters<AzureInputRange> buildInputParams(String path, long from, long size)\n  {\n    ChunkingStorageConnectorParameters.Builder<AzureInputRange> parameters = new ChunkingStorageConnectorParameters.Builder<>();\n    parameters.tempDirSupplier(config::getTempDir);\n    parameters.maxRetry(config.getMaxRetry());\n    parameters.cloudStoragePath(objectPath(path));\n    parameters.retryCondition(AzureUtils.AZURE_RETRY);\n    parameters.start(from);\n    parameters.end(from + size);\n    parameters.objectSupplier((start, end) -> new AzureInputRange(\n        start,\n        end - start,\n        config.getContainer(),\n        objectPath(path)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/azure-extensions/src/main/java/org/apache/druid/storage/azure/output/AzureStorageConnector.java#L50-L86","documentation":"buildInputParams determines the blob size via azureStorage.getBlockBlobLength and wraps BlobStorageException in an IOException. It is thrown when the Azure service rejects the metadata/properties request for the blob at the given path — most commonly because the blob does not exist or the credentials lack read access.","triggerScenarios":"Calling buildInputParams(path) on AzureStorageConnector for a path whose getBlockBlobLength call returns a BlobStorageException: 404 blob not found, 403 auth failure, or 5xx service error while resolving container+objectPath.","commonSituations":"Deep storage path typos or wrong druid.storage.container/prefix so the object path does not exist; firehose/input-source setup pointing at segments not yet published; SAS/key without get-blob-properties permission; transient Azure outages.","solutions":["Verify the blob path exists: az storage blob exists --container-name <c> --name <objectPath>; fix the path/container/prefix config if wrong","Validate credentials grant read/get-properties on the container if the status code is 403","Check the BlobStorageException status code in the IOException cause for 4xx vs 5xx and retry on 5xx/transient errors","If this occurs during ingestion, confirm the segments were successfully published to Azure deep storage first"],"exampleFix":"// before\nparams = connector.buildInputParams(\"unknown/path.json\");\n// after\nif (connector.pathExists(\"unknown/path.json\")) {\n  params = connector.buildInputParams(\"unknown/path.json\");\n} else {\n  throw new ISE(\"Path %s does not exist in Azure container\", \"unknown/path.json\");\n}","handlingStrategy":"validation","validationCode":"if (!connector.pathExists(path)) { throw new IllegalArgumentException(\"Blob not found: \" + path); }\n// then call buildInputParams(path) safely for 404 cases","typeGuard":null,"tryCatchPattern":"try { params = connector.buildInputParams(path); } catch (IOException e) { BlobStorageException b = findCause(e, BlobStorageException.class); if (b != null && b.getStatusCode() == 404) handleMissing(path); else throw e; }","preventionTips":["Confirm the deep storage path/container/prefix config before queries or ingestion read from Azure","For 404 causes, check that the segments were fully published before reading","Retry on 5xx status codes; treat 403 as a credentials problem, not retryable"],"tags":["azure","blob-storage","resource-not-found","wrapper-exception"],"backgroundTag":"resource-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}