jcrist: LGTM. Thanks @metasyn!
diff --git a/dask/array/core.py b/dask/array/core.py
index af23cc282..d7a944784 100644
--- a/dask/array/core.py
+++ b/dask/array/core.py
@@ -1111,6 +1111,8 @@ class Array(Base):
     chunks = property(_get_chunks, _set_chunks, "chunks property")
 
     def __len__(self):
+        if not self.chunks:
+            raise TypeError("len() of unsized object")
         return sum(self.chunks[0])
 
     def __array_ufunc__(self, numpy_ufunc, method, *inputs, **kwargs):
diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst
index e789593ba..823f70472 100644
--- a/docs/source/changelog.rst
+++ b/docs/source/changelog.rst
@@ -7,7 +7,7 @@ Changelog
 
 Array
 +++++
-
+- Update error handling when len is called with empty chunks (:issue:`3058`) `Xander Johnson`_
 
 DataFrame
 +++++++++
@@ -918,3 +918,4 @@ Other
 .. _`Markus Gonser`: https://github.com/magonser
 .. _`Martijn Arts`: https://github.com/mfaafm
 .. _`Jon Mease`: https://github.com/jmmease
+.. _`Xander Johnson`: https://github.com/metasyn

len(dask scalar) gives an error
```
Traceback (most recent call last):
  File "make-pkhalo.py", line 12, in <module>
    print(cath200['Mass'][0])
  File "/home/yfeng1/anaconda3/install/envs/cfastpm/lib/python3.6/site-packages/nbodykit/base/catalog.py", line 75, in __str__
    if len(self) > 0:
  File "/home/yfeng1/anaconda3/install/envs/cfastpm/lib/python3.6/site-packages/dask/array/core.py", line 1064, in __len__
    return sum(self.chunks[0])
IndexError: tuple index out of range
```

The error is probably valid as self is a scalar, but the message could be more informative than an out of range index error. 
diff --git a/dask/array/tests/test_array_core.py b/dask/array/tests/test_array_core.py
index 0eececc3c..a5c76c46d 100644
--- a/dask/array/tests/test_array_core.py
+++ b/dask/array/tests/test_array_core.py
@@ -3032,3 +3032,12 @@ def test_delayed_array_key_hygeine():
     d = delayed(identity)(a)
     b = da.from_delayed(d, shape=a.shape, dtype=a.dtype)
     assert_eq(a, b)
+
+
+def test_empty_chunks_in_array_len():
+    x = da.ones((), chunks=())
+    with pytest.raises(TypeError) as exc_info:
+        len(x)
+
+    err_msg = 'len() of unsized object'
+    assert err_msg in str(exc_info.value)

pip install -e .[complete]
parse_log_pytest
requirements.txt
pytest
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
click==8.0.4
cloudpickle==2.2.1
-e git+https://github.com/dask/dask.git@1223f0167e1f760a93aaf286e6dcfa72ba21f773#egg=dask
distributed==1.20.2
HeapDict==1.0.1
importlib-metadata==4.8.3
iniconfig==1.1.1
locket==1.0.0
msgpack-python==0.5.6
numpy==1.19.5
packaging==21.3
pandas==1.1.5
partd==1.2.0
pluggy==1.0.0
psutil==7.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
six==1.17.0
sortedcontainers==2.4.0
tblib==1.7.0
tomli==1.2.3
toolz==0.12.0
tornado==6.1
typing_extensions==4.1.1
zict==2.1.0
zipp==3.6.0

name: dask
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - click==8.0.4
      - cloudpickle==2.2.1
      - distributed==1.20.2
      - heapdict==1.0.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - locket==1.0.0
      - msgpack-python==0.5.6
      - numpy==1.19.5
      - packaging==21.3
      - pandas==1.1.5
      - partd==1.2.0
      - pluggy==1.0.0
      - psutil==7.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - six==1.17.0
      - sortedcontainers==2.4.0
      - tblib==1.7.0
      - tomli==1.2.3
      - toolz==0.12.0
      - tornado==6.1
      - typing-extensions==4.1.1
      - zict==2.1.0
      - zipp==3.6.0
prefix: /opt/conda/envs/dask

dask/array/tests/test_array_core.py::test_empty_chunks_in_array_len
dask/array/tests/test_array_core.py::test_matmul
dask/array/tests/test_array_core.py::test_getem dask/array/tests/test_array_core.py::test_top dask/array/tests/test_array_core.py::test_top_supports_broadcasting_rules dask/array/tests/test_array_core.py::test_top_literals dask/array/tests/test_array_core.py::test_atop_literals dask/array/tests/test_array_core.py::test_concatenate3_on_scalars dask/array/tests/test_array_core.py::test_chunked_dot_product dask/array/tests/test_array_core.py::test_chunked_transpose_plus_one dask/array/tests/test_array_core.py::test_broadcast_dimensions_works_with_singleton_dimensions dask/array/tests/test_array_core.py::test_broadcast_dimensions dask/array/tests/test_array_core.py::test_Array dask/array/tests/test_array_core.py::test_uneven_chunks dask/array/tests/test_array_core.py::test_numblocks_suppoorts_singleton_block_dims dask/array/tests/test_array_core.py::test_keys dask/array/tests/test_array_core.py::test_Array_computation dask/array/tests/test_array_core.py::test_stack dask/array/tests/test_array_core.py::test_short_stack dask/array/tests/test_array_core.py::test_stack_scalars dask/array/tests/test_array_core.py::test_stack_promote_type dask/array/tests/test_array_core.py::test_stack_rechunk dask/array/tests/test_array_core.py::test_concatenate dask/array/tests/test_array_core.py::test_concatenate_unknown_axes dask/array/tests/test_array_core.py::test_concatenate_rechunk dask/array/tests/test_array_core.py::test_concatenate_fixlen_strings dask/array/tests/test_array_core.py::test_block_simple_row_wise dask/array/tests/test_array_core.py::test_block_simple_column_wise dask/array/tests/test_array_core.py::test_block_with_1d_arrays_row_wise dask/array/tests/test_array_core.py::test_block_with_1d_arrays_multiple_rows dask/array/tests/test_array_core.py::test_block_with_1d_arrays_column_wise dask/array/tests/test_array_core.py::test_block_mixed_1d_and_2d dask/array/tests/test_array_core.py::test_block_complicated dask/array/tests/test_array_core.py::test_block_nested dask/array/tests/test_array_core.py::test_block_3d dask/array/tests/test_array_core.py::test_block_with_mismatched_shape dask/array/tests/test_array_core.py::test_block_no_lists dask/array/tests/test_array_core.py::test_block_invalid_nesting dask/array/tests/test_array_core.py::test_block_empty_lists dask/array/tests/test_array_core.py::test_block_tuple dask/array/tests/test_array_core.py::test_binops dask/array/tests/test_array_core.py::test_broadcast_shapes dask/array/tests/test_array_core.py::test_elemwise_on_scalars dask/array/tests/test_array_core.py::test_elemwise_with_ndarrays dask/array/tests/test_array_core.py::test_elemwise_differently_chunked dask/array/tests/test_array_core.py::test_elemwise_dtype dask/array/tests/test_array_core.py::test_operators dask/array/tests/test_array_core.py::test_operator_dtype_promotion dask/array/tests/test_array_core.py::test_field_access dask/array/tests/test_array_core.py::test_field_access_with_shape dask/array/tests/test_array_core.py::test_T dask/array/tests/test_array_core.py::test_norm dask/array/tests/test_array_core.py::test_broadcast_to dask/array/tests/test_array_core.py::test_broadcast_to_array dask/array/tests/test_array_core.py::test_broadcast_to_scalar dask/array/tests/test_array_core.py::test_broadcast_to_chunks dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape0-v_shape0] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape1-v_shape1] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape2-v_shape2] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape3-v_shape3] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape4-v_shape4] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape5-v_shape5] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape6-v_shape6] dask/array/tests/test_array_core.py::test_reshape[original_shape0-new_shape0-chunks0] dask/array/tests/test_array_core.py::test_reshape[original_shape1-new_shape1-5] dask/array/tests/test_array_core.py::test_reshape[original_shape2-new_shape2-5] dask/array/tests/test_array_core.py::test_reshape[original_shape3-new_shape3-12] dask/array/tests/test_array_core.py::test_reshape[original_shape4-new_shape4-12] dask/array/tests/test_array_core.py::test_reshape[original_shape5-new_shape5-chunks5] dask/array/tests/test_array_core.py::test_reshape[original_shape6-new_shape6-4] dask/array/tests/test_array_core.py::test_reshape[original_shape7-new_shape7-4] dask/array/tests/test_array_core.py::test_reshape[original_shape8-new_shape8-4] dask/array/tests/test_array_core.py::test_reshape[original_shape9-new_shape9-2] dask/array/tests/test_array_core.py::test_reshape[original_shape10-new_shape10-2] dask/array/tests/test_array_core.py::test_reshape[original_shape11-new_shape11-2] dask/array/tests/test_array_core.py::test_reshape[original_shape12-new_shape12-2] dask/array/tests/test_array_core.py::test_reshape[original_shape13-new_shape13-2] dask/array/tests/test_array_core.py::test_reshape[original_shape14-new_shape14-2] dask/array/tests/test_array_core.py::test_reshape[original_shape15-new_shape15-2] dask/array/tests/test_array_core.py::test_reshape[original_shape16-new_shape16-chunks16] dask/array/tests/test_array_core.py::test_reshape[original_shape17-new_shape17-3] dask/array/tests/test_array_core.py::test_reshape[original_shape18-new_shape18-4] dask/array/tests/test_array_core.py::test_reshape[original_shape19-new_shape19-chunks19] dask/array/tests/test_array_core.py::test_reshape[original_shape20-new_shape20-1] dask/array/tests/test_array_core.py::test_reshape[original_shape21-new_shape21-1] dask/array/tests/test_array_core.py::test_reshape[original_shape22-new_shape22-24] dask/array/tests/test_array_core.py::test_reshape[original_shape23-new_shape23-6] dask/array/tests/test_array_core.py::test_reshape[original_shape24-new_shape24-6] dask/array/tests/test_array_core.py::test_reshape[original_shape25-new_shape25-6] dask/array/tests/test_array_core.py::test_reshape[original_shape26-new_shape26-chunks26] dask/array/tests/test_array_core.py::test_reshape[original_shape27-new_shape27-chunks27] dask/array/tests/test_array_core.py::test_reshape[original_shape28-new_shape28-chunks28] dask/array/tests/test_array_core.py::test_reshape[original_shape29-new_shape29-chunks29] dask/array/tests/test_array_core.py::test_reshape[original_shape30-new_shape30-chunks30] dask/array/tests/test_array_core.py::test_reshape[original_shape31-new_shape31-chunks31] dask/array/tests/test_array_core.py::test_reshape[original_shape32-new_shape32-chunks32] dask/array/tests/test_array_core.py::test_reshape[original_shape33-new_shape33-chunks33] dask/array/tests/test_array_core.py::test_reshape[original_shape34-new_shape34-chunks34] dask/array/tests/test_array_core.py::test_reshape_exceptions dask/array/tests/test_array_core.py::test_reshape_splat dask/array/tests/test_array_core.py::test_reshape_fails_for_dask_only dask/array/tests/test_array_core.py::test_reshape_unknown_dimensions dask/array/tests/test_array_core.py::test_full dask/array/tests/test_array_core.py::test_map_blocks dask/array/tests/test_array_core.py::test_map_blocks2 dask/array/tests/test_array_core.py::test_map_blocks_with_constants dask/array/tests/test_array_core.py::test_map_blocks_with_kwargs dask/array/tests/test_array_core.py::test_map_blocks_with_chunks dask/array/tests/test_array_core.py::test_map_blocks_dtype_inference dask/array/tests/test_array_core.py::test_from_function_requires_block_args dask/array/tests/test_array_core.py::test_repr dask/array/tests/test_array_core.py::test_slicing_with_ellipsis dask/array/tests/test_array_core.py::test_slicing_with_ndarray dask/array/tests/test_array_core.py::test_dtype dask/array/tests/test_array_core.py::test_blockdims_from_blockshape dask/array/tests/test_array_core.py::test_coerce dask/array/tests/test_array_core.py::test_bool dask/array/tests/test_array_core.py::test_store_delayed_target dask/array/tests/test_array_core.py::test_store dask/array/tests/test_array_core.py::test_store_regions dask/array/tests/test_array_core.py::test_store_compute_false dask/array/tests/test_array_core.py::test_store_locks dask/array/tests/test_array_core.py::test_to_dask_dataframe dask/array/tests/test_array_core.py::test_np_array_with_zero_dimensions dask/array/tests/test_array_core.py::test_dtype_complex dask/array/tests/test_array_core.py::test_astype dask/array/tests/test_array_core.py::test_arithmetic dask/array/tests/test_array_core.py::test_elemwise_consistent_names dask/array/tests/test_array_core.py::test_optimize dask/array/tests/test_array_core.py::test_slicing_with_non_ndarrays dask/array/tests/test_array_core.py::test_getter dask/array/tests/test_array_core.py::test_size dask/array/tests/test_array_core.py::test_nbytes dask/array/tests/test_array_core.py::test_itemsize dask/array/tests/test_array_core.py::test_Array_normalizes_dtype dask/array/tests/test_array_core.py::test_from_array_with_lock dask/array/tests/test_array_core.py::test_from_array_tasks_always_call_getter dask/array/tests/test_array_core.py::test_from_array_no_asarray dask/array/tests/test_array_core.py::test_from_array_getitem dask/array/tests/test_array_core.py::test_from_array_minus_one dask/array/tests/test_array_core.py::test_asarray dask/array/tests/test_array_core.py::test_asanyarray dask/array/tests/test_array_core.py::test_from_func dask/array/tests/test_array_core.py::test_concatenate3_2 dask/array/tests/test_array_core.py::test_map_blocks3 dask/array/tests/test_array_core.py::test_from_array_with_missing_chunks dask/array/tests/test_array_core.py::test_normalize_chunks dask/array/tests/test_array_core.py::test_raise_on_no_chunks dask/array/tests/test_array_core.py::test_chunks_is_immutable dask/array/tests/test_array_core.py::test_raise_on_bad_kwargs dask/array/tests/test_array_core.py::test_long_slice dask/array/tests/test_array_core.py::test_ellipsis_slicing dask/array/tests/test_array_core.py::test_point_slicing dask/array/tests/test_array_core.py::test_point_slicing_with_full_slice dask/array/tests/test_array_core.py::test_slice_with_floats dask/array/tests/test_array_core.py::test_slice_with_integer_types dask/array/tests/test_array_core.py::test_index_with_integer_types dask/array/tests/test_array_core.py::test_vindex_basic dask/array/tests/test_array_core.py::test_vindex_nd dask/array/tests/test_array_core.py::test_vindex_negative dask/array/tests/test_array_core.py::test_vindex_errors dask/array/tests/test_array_core.py::test_vindex_merge dask/array/tests/test_array_core.py::test_empty_array dask/array/tests/test_array_core.py::test_memmap dask/array/tests/test_array_core.py::test_to_npy_stack dask/array/tests/test_array_core.py::test_view dask/array/tests/test_array_core.py::test_view_fortran dask/array/tests/test_array_core.py::test_map_blocks_with_changed_dimension dask/array/tests/test_array_core.py::test_broadcast_chunks dask/array/tests/test_array_core.py::test_chunks_error dask/array/tests/test_array_core.py::test_array_compute_forward_kwargs dask/array/tests/test_array_core.py::test_dont_fuse_outputs dask/array/tests/test_array_core.py::test_dont_dealias_outputs dask/array/tests/test_array_core.py::test_timedelta_op dask/array/tests/test_array_core.py::test_to_delayed dask/array/tests/test_array_core.py::test_to_delayed_optimizes dask/array/tests/test_array_core.py::test_cumulative dask/array/tests/test_array_core.py::test_atop_names dask/array/tests/test_array_core.py::test_atop_new_axes dask/array/tests/test_array_core.py::test_atop_kwargs dask/array/tests/test_array_core.py::test_atop_chunks dask/array/tests/test_array_core.py::test_from_delayed dask/array/tests/test_array_core.py::test_A_property dask/array/tests/test_array_core.py::test_copy_mutate dask/array/tests/test_array_core.py::test_npartitions dask/array/tests/test_array_core.py::test_astype_gh1151 dask/array/tests/test_array_core.py::test_elemwise_name dask/array/tests/test_array_core.py::test_map_blocks_name dask/array/tests/test_array_core.py::test_array_picklable dask/array/tests/test_array_core.py::test_from_array_raises_on_bad_chunks dask/array/tests/test_array_core.py::test_concatenate_axes dask/array/tests/test_array_core.py::test_atop_concatenate dask/array/tests/test_array_core.py::test_common_blockdim dask/array/tests/test_array_core.py::test_uneven_chunks_that_fit_neatly dask/array/tests/test_array_core.py::test_elemwise_uneven_chunks dask/array/tests/test_array_core.py::test_uneven_chunks_atop dask/array/tests/test_array_core.py::test_warn_bad_rechunking dask/array/tests/test_array_core.py::test_optimize_fuse_keys dask/array/tests/test_array_core.py::test_concatenate_stack_dont_warn dask/array/tests/test_array_core.py::test_map_blocks_delayed dask/array/tests/test_array_core.py::test_no_chunks dask/array/tests/test_array_core.py::test_no_chunks_2d dask/array/tests/test_array_core.py::test_no_chunks_yes_chunks dask/array/tests/test_array_core.py::test_raise_informative_errors_no_chunks dask/array/tests/test_array_core.py::test_no_chunks_slicing_2d dask/array/tests/test_array_core.py::test_index_array_with_array_1d dask/array/tests/test_array_core.py::test_index_array_with_array_2d dask/array/tests/test_array_core.py::test_setitem_1d dask/array/tests/test_array_core.py::test_setitem_2d dask/array/tests/test_array_core.py::test_setitem_errs dask/array/tests/test_array_core.py::test_zero_slice_dtypes dask/array/tests/test_array_core.py::test_zero_sized_array_rechunk dask/array/tests/test_array_core.py::test_atop_zero_shape dask/array/tests/test_array_core.py::test_atop_zero_shape_new_axes dask/array/tests/test_array_core.py::test_broadcast_against_zero_shape dask/array/tests/test_array_core.py::test_from_array_name dask/array/tests/test_array_core.py::test_concatenate_errs dask/array/tests/test_array_core.py::test_stack_errs dask/array/tests/test_array_core.py::test_atop_with_numpy_arrays dask/array/tests/test_array_core.py::test_elemwise_with_lists[other0-100] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other0-6] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other1-100] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other1-6] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other2-100] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other2-6] dask/array/tests/test_array_core.py::test_constructor_plugin dask/array/tests/test_array_core.py::test_no_warnings_on_metadata dask/array/tests/test_array_core.py::test_delayed_array_key_hygeine
docs/source/changelog.rst dask/array/core.py
docs/source/changelog.rst dask/array/core.py