Distributed binaries always exit 0 on handled errors: starters/icloudpd.py calls cli() without sys.exit()

Author: danielpcoxCreated Aug 22, 2026Updated Aug 22, 2026

Overview

icloudpd exits with status 0 even when it fails with a handled error (connection error, API error, failed login, ...). The Python code returns the right codes, but the PyInstaller entry script discards them.

src/starters/icloudpd.py:

python
from icloudpd.cli import cli

if __name__ == "__main__":
    cli()          # return value (1 / 2) is dropped -> process exits 0

cli() returns run_with_configs(...), which propagates core_single_run()'s return 1 for PyiCloudConnectionErrorException, PyiCloudAPIResponseException, PyiCloudFailedLoginException, etc., and return 2 for argument validation errors — but nothing calls sys.exit() on that value, so the exit status is always 0 unless an unhandled exception escapes.

This affects everything built from that starter: the PyPI wheels (the console script icloudpdicloudpd/__main__.pysubprocess.call(<bundled binary>) correctly propagates the binary's code, but the binary itself is already 0), the GitHub release binaries, and the Docker image. A source/editable install using the [project.scripts] icloudpd = "icloudpd.cli:cli" entry point is not affected, because the setuptools wrapper does sys.exit(cli()).

Steps to reproduce

bash
# pip install icloudpd==1.32.3 in a venv (linux x86_64), then force a connection error:
HTTPS_PROXY=http://127.0.0.1:9 icloudpd --password-provider parameter --no-progress-bar \
  --cookie-directory /tmp/x --directory /tmp/x --username [email protected] --password x
# 2026-08-22 22:47:50 INFO     Processing user: [email protected]
# 2026-08-22 22:47:50 INFO     Cannot connect to Apple iCloud service
echo $?
# 0

Same result invoking the bundled binary (site-packages/icloudpd/icloudpd) directly.

Real-world impact

I run icloudpd from a systemd timer with OnFailure= alerting. A full-library pass (21,250 assets) died after 12,822 with Cannot connect to Apple iCloud service; the unit recorded ExecMainStatus=0, no alert fired, and the next hourly incremental run reported success on top of a half-done library. Anyone using the exit status in cron/systemd/Docker health logic is affected the same way. (Note also that the connection error is logged at INFO level, which makes it even easier to miss.)

Suggested fix

python
import sys
from icloudpd.cli import cli

if __name__ == "__main__":
    sys.exit(cli())

(and possibly the same for src/starters/icloud.py if it has the same shape). Happy to open a PR if that's welcome.

Environment

  • icloudpd 1.32.3 (version:1.32.3, commit sha:2035bb1), PyPI wheel icloudpd-1.32.3-py2.py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.whl
  • Debian 13 (LXC), Python 3.13.5 venv

Source: icloud-photos-downloader/icloud_photos_downloader