119
119
from zarr .core .sync import sync
120
120
from zarr .errors import (
121
121
ArrayNotFoundError ,
122
+ ContainsArrayError ,
122
123
MetadataValidationError ,
123
124
ZarrDeprecationWarning ,
124
125
ZarrUserWarning ,
@@ -1496,14 +1497,23 @@ async def _save_metadata(self, metadata: ArrayMetadata, ensure_parents: bool = F
1496
1497
Asynchronously save the array metadata.
1497
1498
"""
1498
1499
to_save = metadata .to_buffer_dict (cpu_buffer_prototype )
1499
- awaitables = [set_or_delete (self .store_path / key , value ) for key , value in to_save .items ()]
1500
+ set_awaitables = [
1501
+ set_or_delete (self .store_path / key , value ) for key , value in to_save .items ()
1502
+ ]
1500
1503
1501
1504
if ensure_parents :
1502
1505
# To enable zarr.create(store, path="a/b/c"), we need to create all the intermediate groups.
1503
1506
parents = _build_parents (self )
1507
+ ensure_array_awaitables = []
1504
1508
1505
1509
for parent in parents :
1506
- awaitables .extend (
1510
+ # Error if an array already exists at any parent location. Only groups can have child nodes.
1511
+ ensure_array_awaitables .append (
1512
+ ensure_no_existing_node (
1513
+ parent .store_path , metadata .zarr_format , node_type = "array"
1514
+ )
1515
+ )
1516
+ set_awaitables .extend (
1507
1517
[
1508
1518
(parent .store_path / key ).set_if_not_exists (value )
1509
1519
for key , value in parent .metadata .to_buffer_dict (
@@ -1512,7 +1522,16 @@ async def _save_metadata(self, metadata: ArrayMetadata, ensure_parents: bool = F
1512
1522
]
1513
1523
)
1514
1524
1515
- await gather (* awaitables )
1525
+ # Checks for parent arrays must happen first, before any metadata is modified
1526
+ try :
1527
+ await gather (* ensure_array_awaitables )
1528
+ except ContainsArrayError as e :
1529
+ set_awaitables = [] # clear awaitables to avoid printed RuntimeWarning: coroutine was never awaited
1530
+ raise ValueError (
1531
+ f"A parent of { self .store_path } is an array - only groups may have child nodes."
1532
+ ) from e
1533
+
1534
+ await gather (* set_awaitables )
1516
1535
1517
1536
async def _set_selection (
1518
1537
self ,
0 commit comments