Unhandled KeyError: 'dsInfo' in requires_2fa when session cookie is invalidated (HTTP 421)

Author: artushinCreated Jul 29, 2026Updated Jul 29, 2026

Overview

When the Apple session cookie has been invalidated, icloudpd crashes with an unhandled KeyError: 'dsInfo' instead of reporting an authentication failure. Exit code is 1 and there is no actionable error message.

Apple returns HTTP 421 from POST https://setup.icloud.com/setup/ws/1/validate with the body:

json
{"success": false, ..., "error": "Missing X-APPLE-WEBAUTH-TOKEN cookie"}

Note that this response does include a trustTokens array and requestInfo, but it has no dsInfo key.

icloudpd logs ERROR Authentication required for Account. (421) and then crashes.

Steps to Reproduce

  1. Invalidate or remove the session cookie in the --cookie-directory.
  2. Run any command that authenticates, e.g.:
icloudpd --username <user> --auth-only --cookie-directory <dir> --password-provider console --mfa-provider console

Environment:

  • Version 1.32.3, commit sha 2035bb1, commit timestamp Sat May 30 11:20:46 2026 CDT (from icloudpd --version)
  • Installed as the PyPI wheel; the pip console script shims into a PyInstaller-frozen bundle at site-packages/icloudpd/icloudpd
  • Linux aarch64, Python 3.12, running headless/unattended via a systemd timer

Observed reproducibly on 9 consecutive daily unattended runs, 2026-07-21 through 2026-07-29 — byte-identical failure each time apart from timestamps and the [PYI-<pid>] value.

Expected Behavior

icloudpd reports an authentication failure (a classified auth error / PyiCloud* exception) so the operator knows an interactive re-auth is required.

Actual Behavior

Traceback (most recent call last):
  File "starters/icloudpd.py", line 6, in <module>
  File "icloudpd/cli.py", line 609, in cli
  File "icloudpd/base.py", line 261, in run_with_configs
  File "icloudpd/base.py", line 438, in _process_all_users_once
  File "icloudpd/base.py", line 902, in core_single_run
  File "icloudpd/authentication.py", line 104, in authenticator
  File "pyicloud_ipd/base.py", line 642, in requires_2fa
KeyError: 'dsInfo'
[PYI-671579:ERROR] Failed to execute script 'icloudpd' due to unhandled exception!

Context

Apparent cause. requires_2fa indexes dsInfo on the validate response unconditionally. On an invalidated/expired session that key is absent, so it raises KeyError rather than surfacing the auth failure. At commit 2035bb1, src/pyicloud_ipd/base.py:

python
@property
def requires_2sa(self) -> bool:
    """Returns True if two-step authentication is required."""
    return self.data.get("dsInfo", {}).get("hsaVersion", 0) >= 1 and (   # line 634 — defensive
        ...

@property
def requires_2fa(self) -> bool:
    """Returns True if two-factor authentication is required."""
    return (
        self.data["dsInfo"].get("hsaVersion", 0) == 2                     # line 642 — raises
        and (self.data.get("hsaChallengeRequired", False) or not self.is_trusted_session)
        and self.data["dsInfo"].get("hasICloudQualifyingDevice", False)
    )

The adjacent requires_2sa already handles a missing dsInfo via .get("dsInfo", {}); requires_2fa does not.

Impact for unattended use. Because the failure is a crash rather than a classified auth error, log-based failure classification cannot distinguish it from an arbitrary error, so automated pipelines cannot tell the operator that an interactive re-auth is required.

Suggested fix. In requires_2fa, handle a missing dsInfo (e.g. .get("dsInfo", {}), matching requires_2sa) and raise the appropriate authentication exception so callers see an auth failure rather than a KeyError.

Source: icloud-photos-downloader/icloud_photos_downloader