Skip to content

InvalidFileException thrown while building XMP sidecar. #1277

@teh-hippo

Description

@teh-hippo

Overview

While creating the XMP sidecars for an image, current release will crashes with an error pointing to Line#133 of xmp_sidecar.py.

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 1084, in core_single_run
  File "icloudpd/base.py", line 731, in download_builder
  File "icloudpd/xmp_sidecar.py", line 71, in generate_xmp_file
  File "icloudpd/xmp_sidecar.py", line 131, in build_metadata
  File "plistlib.py", line 916, in loads
  File "plistlib.py", line 897, in load
plistlib.InvalidFileException: Invalid file

Or from a developer instance:

2025-11-21 01:31:55 DEBUG    Photos/2015/IMG_1928.JPG already exists
Traceback (most recent call last):
  File "/home/vscode/.local/bin/icloudpd", line 7, in <module>
    sys.exit(cli())
             ~~~^^
  File "/workspaces/icloud_photos_downloader/src/icloudpd/cli.py", line 624, in cli
    return run_with_configs(global_ns, user_nses)
  File "/workspaces/icloud_photos_downloader/src/icloudpd/base.py", line 287, in run_with_configs
    return _process_all_users_once(global_config, user_configs, logger, shared_status_exchange)
  File "/workspaces/icloud_photos_downloader/src/icloudpd/base.py", line 464, in _process_all_users_once
    result = core_single_run(
        logger,
    ...<7 lines>...
        lp_filename_generator,
    )
  File "/workspaces/icloud_photos_downloader/src/icloudpd/base.py", line 1380, in core_single_run
    download_result = download_photo(consecutive_files_found, item)
  File "/workspaces/icloud_photos_downloader/src/icloudpd/base.py", line 789, in download_builder
    generate_xmp_file(logger, download_path, photo._asset_record, dry_run)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspaces/icloud_photos_downloader/src/icloudpd/xmp_sidecar.py", line 71, in generate_xmp_file
    xmp_metadata: XMPMetadata = build_metadata(asset_record)
                                ~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "/workspaces/icloud_photos_downloader/src/icloudpd/xmp_sidecar.py", line 133, in build_metadata
    location = plistlib.loads(
        base64.b64decode(asset_record["fields"]["locationEnc"]["value"]),
    )
  File "/usr/local/lib/python3.13/plistlib.py", line 916, in loads
    return load(fp, fmt=fmt, dict_type=dict_type, aware_datetime=aware_datetime)
  File "/usr/local/lib/python3.13/plistlib.py", line 897, in load
    raise InvalidFileException()
plistlib.InvalidFileException: Invalid file

In trying to look into why, I saw #1059, and applied similar debugging steps to produce some output.

For asset_record["fields"]["locationEnc"]["value"], my image has a value of: PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8YXJyYXkvPgo8L3BsaXN0Pgo=

This decodes to:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array/>
</plist>

Steps to Reproduce

I'm using the latest version, and have been executing:
icloudpd -u my@email.com --directory /mnt/e/icloudpd --library SharedSync-LONG-GUID-THING --xmp-sidecar --set-exif-datetime --skip-videos --folder-structure '{:%Y}'

That won't help without my photo.
I pulled the code, and tried applying that value to a test in test_xmp_sidecar.py:

        # Test Blank
        assetRecordStub["fields"]["locationEnc"]["value"] = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8YXJyYXkvPgo8L3BsaXN0Pgo="
        metadata = build_metadata(assetRecordStub)

That crashes with a slightly different stack-trace to the above:

            location = plistlib.loads(
                base64.b64decode(asset_record["fields"]["locationEnc"]["value"]),
            )
>           gps_altitude = location.get("alt")
                           ^^^^^^^^^^^^
E           AttributeError: 'list' object has no attribute 'get'

src/icloudpd/xmp_sidecar.py:136: AttributeError

I'm not familiar with the project (or Python really).
Not sure why its different, but potentially its unit test vs. actual.
Seems core crashes in plistlib itself, but this doesn't reproduce the exact same stack either:

# Added hackily into `test_xmp_sidecar.py`...

import base64
import plistlib

        print ("trying this out")
        location = plistlib.loads(
            base64.b64decode("PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8YXJyYXkvPgo8L3BsaXN0Pgo="),
        )
        assert location is None

Expected Behavior

Continuing without error.
Seems that the image has an invalid / empty set of metadata built into it.
I'd suggest that field be discarded if its in such a format, or checked during parsing.

Actual Behavior

Crashes with the above stack trace.

Context

I can provide the file privately if that's easier, but I'd rather not share personal photos unnecessarily.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions