diff --git a/ddsc/core/download.py b/ddsc/core/download.py
index f9bf81b..545d438 100644
--- a/ddsc/core/download.py
+++ b/ddsc/core/download.py
@@ -439,6 +439,7 @@ class RetryChunkDownloader(object):
         if response.status_code == 401:
             raise DownloadInconsistentError(response.text)
         response.raise_for_status()
+        self.actual_bytes_read = 0
         self._write_response_to_file(response)
         self._verify_download_complete()
 

User received TooLargeChunkDownloadError exception
User was downloading a project via `ddsclient download -p <projectname> --include <filepath>`.

Error:
```
  File ".../conda/envs/bespin/lib/python3.7/site-packages/ddsc/core/download.py", line 455, 
in _write_response_to_file
    self._on_bytes_read(len(chunk))
  File ".../conda/envs/bespin/lib/python3.7/site-packages/ddsc/core/download.py", line 464, 
in _on_bytes_read
    raise TooLargeChunkDownloadError(self.actual_bytes_read, self.bytes_to_read, 
  self.local_path)

ddsc.core.download.TooLargeChunkDownloadError: 
Received too many bytes downloading part of a file. 
Actual: 44159228 Expected: 32963486 File: <filename>
```

I was unable to reproduce the issue the same file downloaded fine for me.
In this place in the code we are reading from a GET request with `Range` headers delimited to the part of the file we are downloading. So we should only receive the amount we are expecting.
This exception was added to catch the unlikely case that we received more than we asked for. 


diff --git a/ddsc/core/tests/test_download.py b/ddsc/core/tests/test_download.py
index 4fa9275..7535a22 100644
--- a/ddsc/core/tests/test_download.py
+++ b/ddsc/core/tests/test_download.py
@@ -541,3 +541,41 @@ class TestRetryChunkDownloader(TestCase):
 
         with self.assertRaises(PartialChunkDownloadError):
             downloader._verify_download_complete()
+
+    @patch('ddsc.core.download.RemoteFileUrl')
+    @patch('ddsc.core.download.requests')
+    def test_retry_download_loop_too_few_actual_bytes_read(self, mock_requests, mock_remote_file_url):
+        mock_requests.exceptions.ConnectionError = ValueError
+        mock_project_file = Mock()
+        mock_context = Mock()
+        downloader = RetryChunkDownloader(project_file=mock_project_file, local_path=None, seek_amt=0,
+                                          bytes_to_read=100, download_context=mock_context)
+        downloader.max_retry_times = 2
+        downloader.get_url_and_headers_for_range = Mock()
+        downloader.get_url_and_headers_for_range.return_value = ('someurl', ['headers'])
+        mock_requests.get.return_value.iter_content.return_value = ['X' * 10]
+        fake_open = mock_open()
+        with patch('ddsc.core.download.open', fake_open, create=True):
+            with self.assertRaises(PartialChunkDownloadError):
+                downloader.retry_download_loop()
+        self.assertEqual(downloader.actual_bytes_read, 10)
+
+    @patch('ddsc.core.download.RemoteFileUrl')
+    @patch('ddsc.core.download.requests')
+    def test_retry_download_loop_too_few_actual_bytes_read_then_works(self, mock_requests, mock_remote_file_url):
+        mock_requests.exceptions.ConnectionError = ValueError
+        mock_project_file = Mock()
+        mock_context = Mock()
+        downloader = RetryChunkDownloader(project_file=mock_project_file, local_path=None, seek_amt=0,
+                                          bytes_to_read=100, download_context=mock_context)
+        downloader.max_retry_times = 2
+        downloader.get_url_and_headers_for_range = Mock()
+        downloader.get_url_and_headers_for_range.return_value = ('someurl', ['headers'])
+        mock_requests.get.return_value.iter_content.side_effect = [
+            ['X' * 10],  # only 10 bytes the first time
+            ['X' * 100],  # all 100 bytes the second time
+        ]
+        fake_open = mock_open()
+        with patch('ddsc.core.download.open', fake_open, create=True):
+            downloader.retry_download_loop()
+        self.assertEqual(downloader.actual_bytes_read, 100)

pip install -e .[dev]
parse_log_pytest
requirements.txt
mock flake8 nose coveralls pytest
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
coverage==7.8.0
coveralls==4.0.1
docopt==0.6.2
-e git+https://github.com/Duke-GCB/DukeDSClient.git@e2cf592ba0d9b2ee1bfdf51a723677275fee3998#egg=DukeDSClient
exceptiongroup==1.2.2
flake8==7.2.0
future==0.16.0
iniconfig==2.1.0
mccabe==0.7.0
mock==5.2.0
nose==1.3.7
packaging==24.2
pluggy==1.5.0
pycodestyle==2.13.0
pyflakes==3.3.1
pytest==8.3.5
pytz==2025.2
PyYAML==3.12
requests==2.13.0
six==1.10.0
tomli==2.2.1

name: DukeDSClient
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
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - 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=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.8.0
      - coveralls==4.0.1
      - docopt==0.6.2
      - exceptiongroup==1.2.2
      - flake8==7.2.0
      - future==0.16.0
      - iniconfig==2.1.0
      - mccabe==0.7.0
      - mock==5.2.0
      - nose==1.3.7
      - packaging==24.2
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.1
      - pytest==8.3.5
      - pytz==2025.2
      - pyyaml==3.12
      - requests==2.13.0
      - six==1.10.0
      - tomli==2.2.1
prefix: /opt/conda/envs/DukeDSClient

ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop_too_few_actual_bytes_read ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop_too_few_actual_bytes_read_then_works
ddsc/core/tests/test_download.py::TestProjectDownload::test_check_warnings ddsc/core/tests/test_download.py::TestProjectDownload::test_include_project_file ddsc/core/tests/test_download.py::TestProjectDownload::test_run ddsc/core/tests/test_download.py::TestProjectDownload::test_run_preprocessor ddsc/core/tests/test_download.py::TestDownloadSettings::test_get_data_service_auth_data ddsc/core/tests/test_download.py::TestDownloadContext::test_create_data_service ddsc/core/tests/test_download.py::TestDownloadContext::test_create_remote_store ddsc/core/tests/test_download.py::TestDownloadContext::test_send_error_message ddsc/core/tests/test_download.py::TestDownloadContext::test_send_message ddsc/core/tests/test_download.py::TestDownloadContext::test_send_processed_message ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_check_downloaded_files_sizes ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_check_file_size ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_determine_bytes_per_chunk ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_download_files ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_make_big_empty_files ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_make_local_directories ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_make_ranges ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_split_file_urls_by_size ddsc/core/tests/test_download.py::TestDownloadFilePartCommand::test_create_context ddsc/core/tests/test_download.py::TestDownloadFilePartCommand::test_on_message_error ddsc/core/tests/test_download.py::TestDownloadFilePartCommand::test_on_message_processed ddsc/core/tests/test_download.py::TestDownloadFilePartRun::test_download_file_part_run ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_download_chunk_inconsistent ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_download_chunk_works ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_get_range_headers ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_get_url_and_headers_for_range ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_on_bytes_read ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_on_bytes_read_too_much ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop_raises_when_out_of_retries ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop_retries_then_works ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_run_handles_exception ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_verify_download_complete_ok ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_verify_download_complete_partial ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_verify_download_complete_too_large
ddsc/core/download.py
ddsc/core/download.py