Skip to content

Commit c183167

Browse files
authored
GH-48894: [Python][C++] Use base Azure::Core::RequestFailedException instead of final Azure::Storage::StorageException and set minimum nodejs on conda env to 16 for Azurite to work (#48895)
### Rationale for this change nodejs 12 is currently being installed on conda. CI jobs are failing and or segfaulting due to azurite failing with old versions. ``` 2026-01-13T18:32:39.6961900Z #15 [ 9/11] RUN /arrow/ci/scripts/install_azurite.sh 2026-01-13T18:32:39.9624124Z #15 0.417 Node.js version = v12.4.0 2026-01-13T18:32:42.2087322Z #15 2.663 npm WARN deprecated rimraf@ 3.0.2: Rimraf versions prior to v4 are no longer supported 2026-01-13T18:32:42.3917601Z #15 2.846 npm WARN deprecated uuid@ 3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. 2026-01-13T18:32:51.4870197Z #15 11.94 npm WARN deprecated glob@ 7.2.3: Glob versions prior to v9 are no longer supported 2026-01-13T18:32:51.7035681Z #15 12.01 npm WARN deprecated inflight@ 1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 2026-01-13T18:33:02.1406491Z #15 22.59 /opt/conda/envs/arrow/bin/azurite -> /opt/conda/envs/arrow/lib/node_modules/azurite/dist/src/azurite.js 2026-01-13T18:33:02.3841290Z #15 22.60 /opt/conda/envs/arrow/bin/azurite-queue -> /opt/conda/envs/arrow/lib/node_modules/azurite/dist/src/queue/main.js 2026-01-13T18:33:02.3842792Z #15 22.60 /opt/conda/envs/arrow/bin/azurite-blob -> /opt/conda/envs/arrow/lib/node_modules/azurite/dist/src/blob/main.js 2026-01-13T18:33:02.3844216Z #15 22.60 /opt/conda/envs/arrow/bin/azurite-table -> /opt/conda/envs/arrow/lib/node_modules/azurite/dist/src/table/main.js 2026-01-13T18:33:02.3846002Z #15 22.66 npm WARN applicationinsights@ 2.9.8 requires a peer of applicationinsights-native-metrics@* but none is installed. You must install peer dependencies yourself. 2026-01-13T18:33:02.3847278Z #15 22.66 2026-01-13T18:33:02.3847564Z #15 22.66 + azurite@ 3.35.0 2026-01-13T18:33:02.3848038Z #15 22.66 added 376 packages from 296 contributors in 20.644s 2026-01-13T18:33:02.3848830Z #15 22.69 /opt/conda/envs/arrow/bin/azurite 2026-01-13T18:33:02.8929329Z #15 23.35 /opt/conda/envs/arrow/lib/node_modules/azurite/node_modules/fs-extra/lib/util/async.js:14 2026-01-13T18:33:02.8930231Z #15 23.35 (err) => err ?? new Error('unknown error') 2026-01-13T18:33:02.8930740Z #15 23.35 ^ ``` The job on PyArrow was segfaulting due to an Exception being thrown but not catch. In general we were using `Azure::Storage::StorageException` but `Azure::Core::Http::TransportException` could also be thrown on some cases. Bot are final but inherit from `Azure::Core::RequestFailedException`. ### What changes are included in this PR? - Pin minimum nodejs version to 16 so the failure doesn't happen again. - Update catching `Azure::Storage::StorageException` to `Azure::Core::RequestFailedException` so `Azure::Core::Http::TransportException` is also catch. ### Are these changes tested? Yes on CI. ### Are there any user-facing changes? No * GitHub Issue: #48894 Authored-by: Raúl Cumplido <raulcumplido@gmail.com> Signed-off-by: Raúl Cumplido <raulcumplido@gmail.com>
1 parent 894d6a3 commit c183167

File tree

2 files changed

+43
-42
lines changed

2 files changed

+43
-42
lines changed

ci/conda_env_cpp.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ lz4-c
3939
make
4040
meson
4141
ninja
42-
nodejs
42+
nodejs>=16
4343
orc<2.1.0
4444
pkg-config
4545
python

cpp/src/arrow/filesystem/azurefs.cc

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ Status CrossContainerMoveNotImplemented(const AzureLocation& src,
558558
"' requires moving data between containers, which is not implemented.");
559559
}
560560

561-
bool IsContainerNotFound(const Storage::StorageException& e) {
561+
bool IsContainerNotFound(const Core::RequestFailedException& e) {
562562
// In some situations, only the ReasonPhrase is set and the
563563
// ErrorCode is empty, so we check both.
564564
if (e.ErrorCode == "ContainerNotFound" ||
@@ -782,7 +782,7 @@ class ObjectInputFile final : public io::RandomAccessFile {
782782
content_length_ = properties.Value.BlobSize;
783783
metadata_ = PropertiesToMetadata(properties.Value);
784784
return Status::OK();
785-
} catch (const Storage::StorageException& exception) {
785+
} catch (const Core::RequestFailedException& exception) {
786786
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
787787
return PathNotFound(location_);
788788
}
@@ -864,7 +864,7 @@ class ObjectInputFile final : public io::RandomAccessFile {
864864
return blob_client_
865865
->DownloadTo(reinterpret_cast<uint8_t*>(out), nbytes, download_options)
866866
.Value.ContentRange.Length.Value();
867-
} catch (const Storage::StorageException& exception) {
867+
} catch (const Core::RequestFailedException& exception) {
868868
return ExceptionToStatus(
869869
exception, "DownloadTo from '", blob_client_->GetUrl(), "' at position ",
870870
position, " for ", nbytes,
@@ -916,7 +916,7 @@ class ObjectInputFile final : public io::RandomAccessFile {
916916
Status CreateEmptyBlockBlob(const Blobs::BlockBlobClient& block_blob_client) {
917917
try {
918918
block_blob_client.UploadFrom(nullptr, 0);
919-
} catch (const Storage::StorageException& exception) {
919+
} catch (const Core::RequestFailedException& exception) {
920920
return ExceptionToStatus(
921921
exception, "UploadFrom failed for '", block_blob_client.GetUrl(),
922922
"'. There is no existing blob at this location or the existing blob must be "
@@ -929,7 +929,7 @@ Result<Blobs::Models::GetBlockListResult> GetBlockList(
929929
std::shared_ptr<Blobs::BlockBlobClient> block_blob_client) {
930930
try {
931931
return block_blob_client->GetBlockList().Value;
932-
} catch (Storage::StorageException& exception) {
932+
} catch (Core::RequestFailedException& exception) {
933933
return ExceptionToStatus(
934934
exception, "GetBlockList failed for '", block_blob_client->GetUrl(),
935935
"'. Cannot write to a file without first fetching the existing block list.");
@@ -945,7 +945,7 @@ Status CommitBlockList(std::shared_ptr<Storage::Blobs::BlockBlobClient> block_bl
945945
// previously committed blocks.
946946
// https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list?tabs=microsoft-entra-id#request-body
947947
block_blob_client->CommitBlockList(block_ids, options);
948-
} catch (const Storage::StorageException& exception) {
948+
} catch (const Core::RequestFailedException& exception) {
949949
return ExceptionToStatus(
950950
exception, "CommitBlockList failed for '", block_blob_client->GetUrl(),
951951
"'. Committing is required to flush an output/append stream.");
@@ -957,7 +957,7 @@ Status StageBlock(Blobs::BlockBlobClient* block_blob_client, const std::string&
957957
Core::IO::MemoryBodyStream& content) {
958958
try {
959959
block_blob_client->StageBlock(id, content);
960-
} catch (const Storage::StorageException& exception) {
960+
} catch (const Core::RequestFailedException& exception) {
961961
return ExceptionToStatus(
962962
exception, "StageBlock failed for '", block_blob_client->GetUrl(),
963963
"' new_block_id: '", id,
@@ -1023,7 +1023,7 @@ class ObjectAppendStream final : public io::OutputStream {
10231023
}
10241024
content_length_ = properties.Value.BlobSize;
10251025
pos_ = content_length_;
1026-
} catch (const Storage::StorageException& exception) {
1026+
} catch (const Core::RequestFailedException& exception) {
10271027
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
10281028
// No file exists but on flat namespace its possible there is a directory
10291029
// marker or an implied directory. Ensure there is no directory before starting
@@ -1366,7 +1366,7 @@ Result<HNSSupport> CheckIfHierarchicalNamespaceIsEnabled(
13661366
// Azurite issue detected.
13671367
DCHECK(IsDfsEmulator(options));
13681368
return HNSSupport::kDisabled;
1369-
} catch (const Storage::StorageException& exception) {
1369+
} catch (const Core::RequestFailedException& exception) {
13701370
// Flat namespace storage accounts with "soft delete" enabled return
13711371
//
13721372
// "Conflict - This endpoint does not support BlobStorageEvents
@@ -1400,9 +1400,6 @@ Result<HNSSupport> CheckIfHierarchicalNamespaceIsEnabled(
14001400
"Check for Hierarchical Namespace support on '",
14011401
adlfs_client.GetUrl(), "' failed.");
14021402
}
1403-
} catch (const Azure::Core::Http::TransportException& exception) {
1404-
return ExceptionToStatus(exception, "Check for Hierarchical Namespace support on '",
1405-
adlfs_client.GetUrl(), "' failed.");
14061403
} catch (const std::exception& exception) {
14071404
return Status::UnknownError(
14081405
"Check for Hierarchical Namespace support on '", adlfs_client.GetUrl(),
@@ -1436,7 +1433,7 @@ Result<FileInfo> GetContainerPropsAsFileInfo(const AzureLocation& location,
14361433
info.set_type(FileType::Directory);
14371434
info.set_mtime(std::chrono::system_clock::time_point{properties.Value.LastModified});
14381435
return info;
1439-
} catch (const Storage::StorageException& exception) {
1436+
} catch (const Core::RequestFailedException& exception) {
14401437
if (IsContainerNotFound(exception)) {
14411438
info.set_type(FileType::NotFound);
14421439
return info;
@@ -1452,7 +1449,7 @@ Status CreateContainerIfNotExists(const std::string& container_name,
14521449
try {
14531450
container_client.CreateIfNotExists();
14541451
return Status::OK();
1455-
} catch (const Storage::StorageException& exception) {
1452+
} catch (const Core::RequestFailedException& exception) {
14561453
return ExceptionToStatus(exception, "Failed to create a container: ", container_name,
14571454
": ", container_client.GetUrl());
14581455
}
@@ -1545,7 +1542,7 @@ class LeaseGuard {
15451542
DCHECK(release_attempt_pending_);
15461543
try {
15471544
lease_client_->Release();
1548-
} catch (const Storage::StorageException& exception) {
1545+
} catch (const Core::RequestFailedException& exception) {
15491546
return ExceptionToStatus(exception, "Failed to release the ",
15501547
lease_client_->GetLeaseId(), " lease");
15511548
}
@@ -1588,7 +1585,7 @@ class LeaseGuard {
15881585
break_or_expires_at_ =
15891586
std::min(break_or_expires_at_,
15901587
SteadyClock::now() + break_period.ValueOr(std::chrono::seconds{0}));
1591-
} catch (const Storage::StorageException& exception) {
1588+
} catch (const Core::RequestFailedException& exception) {
15921589
return ExceptionToStatus(exception, "Failed to break the ",
15931590
lease_client_->GetLeaseId(), " lease expiring in ",
15941591
remaining_time_ms().count(), "ms");
@@ -1783,7 +1780,7 @@ class AzureFileSystem::Impl {
17831780
info.set_mtime(
17841781
std::chrono::system_clock::time_point{properties.Value.LastModified});
17851782
return info;
1786-
} catch (const Storage::StorageException& exception) {
1783+
} catch (const Core::RequestFailedException& exception) {
17871784
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
17881785
return FileInfo{location.all, FileType::NotFound};
17891786
}
@@ -1858,7 +1855,7 @@ class AzureFileSystem::Impl {
18581855
}
18591856
info.set_type(FileType::NotFound);
18601857
return info;
1861-
} catch (const Storage::StorageException& exception) {
1858+
} catch (const Core::RequestFailedException& exception) {
18621859
if (IsContainerNotFound(exception)) {
18631860
return FileInfo{location.all, FileType::NotFound};
18641861
}
@@ -1918,7 +1915,7 @@ class AzureFileSystem::Impl {
19181915
RETURN_NOT_OK(on_container(container));
19191916
}
19201917
}
1921-
} catch (const Storage::StorageException& exception) {
1918+
} catch (const Core::RequestFailedException& exception) {
19221919
return ExceptionToStatus(exception, "Failed to list account containers.");
19231920
}
19241921
return Status::OK();
@@ -1973,7 +1970,7 @@ class AzureFileSystem::Impl {
19731970
}
19741971
}
19751972
}
1976-
} catch (const Storage::StorageException& exception) {
1973+
} catch (const Core::RequestFailedException& exception) {
19771974
if (IsContainerNotFound(exception) || exception.ErrorCode == "PathNotFound") {
19781975
found = false;
19791976
} else {
@@ -2086,7 +2083,7 @@ class AzureFileSystem::Impl {
20862083
RETURN_NOT_OK(process_prefix(list_response.BlobPrefixes[blob_prefix_index]));
20872084
}
20882085
}
2089-
} catch (const Storage::StorageException& exception) {
2086+
} catch (const Core::RequestFailedException& exception) {
20902087
if (IsContainerNotFound(exception)) {
20912088
found = false;
20922089
} else {
@@ -2225,7 +2222,7 @@ class AzureFileSystem::Impl {
22252222
if (container_info.type() == FileType::NotFound) {
22262223
try {
22272224
container_client.CreateIfNotExists();
2228-
} catch (const Storage::StorageException& exception) {
2225+
} catch (const Core::RequestFailedException& exception) {
22292226
return ExceptionToStatus(exception, "Failed to create directory '",
22302227
location.all, "': ", container_client.GetUrl());
22312228
}
@@ -2252,7 +2249,7 @@ class AzureFileSystem::Impl {
22522249
const auto& nonexistent_location = nonexistent_locations[i - 1];
22532250
try {
22542251
create_if_not_exists(container_client, nonexistent_location);
2255-
} catch (const Storage::StorageException& exception) {
2252+
} catch (const Core::RequestFailedException& exception) {
22562253
return ExceptionToStatus(exception, "Failed to create directory '",
22572254
location.all, "': ", container_client.GetUrl());
22582255
}
@@ -2270,7 +2267,7 @@ class AzureFileSystem::Impl {
22702267
try {
22712268
create_if_not_exists(container_client, location);
22722269
return Status::OK();
2273-
} catch (const Storage::StorageException& exception) {
2270+
} catch (const Core::RequestFailedException& exception) {
22742271
if (IsContainerNotFound(exception)) {
22752272
auto parent = location.parent();
22762273
return PathNotFound(parent);
@@ -2378,7 +2375,7 @@ class AzureFileSystem::Impl {
23782375
try {
23792376
EnsureEmptyDirExistsImplThatThrows(container_client, location.path);
23802377
return Status::OK();
2381-
} catch (const Storage::StorageException& exception) {
2378+
} catch (const Core::RequestFailedException& exception) {
23822379
return ExceptionToStatus(
23832380
exception, operation_name, " failed to ensure empty directory marker '",
23842381
location.path, "' exists in container: ", container_client.GetUrl());
@@ -2396,7 +2393,7 @@ class AzureFileSystem::Impl {
23962393
// Only the "*IfExists" functions ever set Deleted to false.
23972394
// All the others either succeed or throw an exception.
23982395
DCHECK(response.Value.Deleted);
2399-
} catch (const Storage::StorageException& exception) {
2396+
} catch (const Core::RequestFailedException& exception) {
24002397
if (IsContainerNotFound(exception)) {
24012398
return PathNotFound(location);
24022399
}
@@ -2492,7 +2489,7 @@ class AzureFileSystem::Impl {
24922489
if (!deferred_responses.empty()) {
24932490
container_client.SubmitBatch(batch);
24942491
}
2495-
} catch (const Storage::StorageException& exception) {
2492+
} catch (const Core::RequestFailedException& exception) {
24962493
return ExceptionToStatus(exception, "Failed to delete blobs in a directory: ",
24972494
location.path, ": ", container_client.GetUrl());
24982495
}
@@ -2502,7 +2499,7 @@ class AzureFileSystem::Impl {
25022499
try {
25032500
auto delete_result = deferred_response.GetResponse();
25042501
success = delete_result.Value.Deleted;
2505-
} catch (const Storage::StorageException& exception) {
2502+
} catch (const Core::RequestFailedException& exception) {
25062503
success = false;
25072504
}
25082505
if (!success) {
@@ -2521,7 +2518,7 @@ class AzureFileSystem::Impl {
25212518
}
25222519
}
25232520
return Status::OK();
2524-
} catch (const Storage::StorageException& exception) {
2521+
} catch (const Core::RequestFailedException& exception) {
25252522
return ExceptionToStatus(exception,
25262523
"Failed to list blobs in a directory: ", location.path,
25272524
": ", container_client.GetUrl());
@@ -2557,7 +2554,7 @@ class AzureFileSystem::Impl {
25572554
// Only the "*IfExists" functions ever set Deleted to false.
25582555
// All the others either succeed or throw an exception.
25592556
DCHECK(response.Value.Deleted);
2560-
} catch (const Storage::StorageException& exception) {
2557+
} catch (const Core::RequestFailedException& exception) {
25612558
if (exception.ErrorCode == "FilesystemNotFound" ||
25622559
exception.ErrorCode == "PathNotFound") {
25632560
if (require_dir_to_exist) {
@@ -2584,7 +2581,7 @@ class AzureFileSystem::Impl {
25842581
auto sub_directory_client = adlfs_client.GetDirectoryClient(path.Name);
25852582
try {
25862583
sub_directory_client.DeleteRecursive();
2587-
} catch (const Storage::StorageException& exception) {
2584+
} catch (const Core::RequestFailedException& exception) {
25882585
return ExceptionToStatus(
25892586
exception, "Failed to delete a sub directory: ", location.container,
25902587
kDelimiter, path.Name, ": ", sub_directory_client.GetUrl());
@@ -2596,7 +2593,7 @@ class AzureFileSystem::Impl {
25962593
auto sub_file_client = adlfs_client.GetFileClient(path.Name);
25972594
try {
25982595
sub_file_client.Delete();
2599-
} catch (const Storage::StorageException& exception) {
2596+
} catch (const Core::RequestFailedException& exception) {
26002597
return ExceptionToStatus(
26012598
exception, "Failed to delete a sub file: ", location.container,
26022599
kDelimiter, path.Name, ": ", sub_file_client.GetUrl());
@@ -2605,7 +2602,7 @@ class AzureFileSystem::Impl {
26052602
}
26062603
}
26072604
return Status::OK();
2608-
} catch (const Storage::StorageException& exception) {
2605+
} catch (const Core::RequestFailedException& exception) {
26092606
if (missing_dir_ok && exception.StatusCode == Http::HttpStatusCode::NotFound) {
26102607
return Status::OK();
26112608
}
@@ -2634,7 +2631,7 @@ class AzureFileSystem::Impl {
26342631
try {
26352632
[[maybe_unused]] auto result = lease_client->Acquire(lease_duration);
26362633
DCHECK_EQ(result.Value.LeaseId, lease_client->GetLeaseId());
2637-
} catch (const Storage::StorageException& exception) {
2634+
} catch (const Core::RequestFailedException& exception) {
26382635
if (IsContainerNotFound(exception)) {
26392636
if (allow_missing_container) {
26402637
return nullptr;
@@ -2674,7 +2671,7 @@ class AzureFileSystem::Impl {
26742671
try {
26752672
[[maybe_unused]] auto result = lease_client->Acquire(lease_duration);
26762673
DCHECK_EQ(result.Value.LeaseId, lease_client->GetLeaseId());
2677-
} catch (const Storage::StorageException& exception) {
2674+
} catch (const Core::RequestFailedException& exception) {
26782675
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
26792676
if (allow_missing) {
26802677
return nullptr;
@@ -2749,7 +2746,7 @@ class AzureFileSystem::Impl {
27492746
// Only the "*IfExists" functions ever set Deleted to false.
27502747
// All the others either succeed or throw an exception.
27512748
DCHECK(response.Value.Deleted);
2752-
} catch (const Storage::StorageException& exception) {
2749+
} catch (const Core::RequestFailedException& exception) {
27532750
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
27542751
// ErrorCode can be "FilesystemNotFound", "PathNotFound"...
27552752
if (require_file_to_exist) {
@@ -2841,7 +2838,7 @@ class AzureFileSystem::Impl {
28412838
// Only the "*IfExists" functions ever set Deleted to false.
28422839
// All the others either succeed or throw an exception.
28432840
DCHECK(response.Value.Deleted);
2844-
} catch (const Storage::StorageException& exception) {
2841+
} catch (const Core::RequestFailedException& exception) {
28452842
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
28462843
return check_if_location_exists_as_dir();
28472844
}
@@ -2906,7 +2903,7 @@ class AzureFileSystem::Impl {
29062903
if (!dest_is_empty) {
29072904
return NotEmpty(dest);
29082905
}
2909-
} catch (const Storage::StorageException& exception) {
2906+
} catch (const Core::RequestFailedException& exception) {
29102907
return ExceptionToStatus(exception, "Failed to check that '", dest.container,
29112908
"' is empty: ", dest_container_client.GetUrl());
29122909
}
@@ -2936,6 +2933,10 @@ class AzureFileSystem::Impl {
29362933
return ExceptionToStatus(exception, "Failed to rename container '", src.container,
29372934
"' to '", dest.container,
29382935
"': ", blob_service_client_->GetUrl());
2936+
} catch (const Core::RequestFailedException& exception) {
2937+
return ExceptionToStatus(exception, "Failed to rename container '", src.container,
2938+
"' to '", dest.container,
2939+
"': ", blob_service_client_->GetUrl());
29392940
}
29402941
} else if (dest_is_empty) {
29412942
// Even if we deleted the empty dest.container, RenameBlobContainer() would still
@@ -2972,11 +2973,11 @@ class AzureFileSystem::Impl {
29722973
src_lease_guard.BreakBeforeDeletion(kTimeNeededForContainerDeletion);
29732974
src_container_client.Delete(options);
29742975
src_lease_guard.Forget();
2975-
} catch (const Storage::StorageException& exception) {
2976+
} catch (const Core::RequestFailedException& exception) {
29762977
return ExceptionToStatus(exception, "Failed to delete empty container: '",
29772978
src.container, "': ", src_container_client.GetUrl());
29782979
}
2979-
} catch (const Storage::StorageException& exception) {
2980+
} catch (const Core::RequestFailedException& exception) {
29802981
return ExceptionToStatus(exception, "Unable to replace empty container: '",
29812982
dest.all, "': ", dest_container_client.GetUrl());
29822983
}
@@ -3117,7 +3118,7 @@ class AzureFileSystem::Impl {
31173118
src_lease_guard.BreakBeforeDeletion(kTimeNeededForFileOrDirectoryRename);
31183119
src_adlfs_client.RenameFile(src_path, dest_path, options);
31193120
src_lease_guard.Forget();
3120-
} catch (const Storage::StorageException& exception) {
3121+
} catch (const Core::RequestFailedException& exception) {
31213122
// https://learn.microsoft.com/en-gb/rest/api/storageservices/datalakestoragegen2/path/create
31223123
if (exception.StatusCode == Http::HttpStatusCode::NotFound) {
31233124
if (exception.ErrorCode == "PathNotFound") {

0 commit comments

Comments
 (0)