pulumi/pulumi · error · TypeError

AssetArchive assets must be a dictionary

Error message

AssetArchive assets must be a dictionary

What it means

AssetArchive wraps a dictionary of named Assets/Archives. The constructor checks isinstance(assets, dict) and raises TypeError if the argument is any other type (list, tuple, None, etc.), since later serialization relies on dict semantics.

Source

Thrown at sdk/python/lib/pulumi/asset.py:88

        self.uri = uri


class Archive:
    """
    Archive represents a collection of named assets.
    """


class AssetArchive(Archive):
    """
    An AssetArchive is an archive created from an in-memory collection of named assets or other archives.
    """

    assets: dict[str, Union[Asset, Archive]]

    def __init__(self, assets: dict[str, Union[Asset, Archive]]) -> None:
        if not isinstance(assets, dict):
            raise TypeError("AssetArchive assets must be a dictionary")
        for k, v in assets.items():
            if not isinstance(k, str):
                raise TypeError("AssetArchive keys must be strings")
            if not isinstance(v, Asset) and not isinstance(v, Archive):
                raise TypeError(
                    "AssetArchive assets must contain only Assets or Archives"
                )
        self.assets = assets


class FileArchive(Archive):
    """
    A FileArchive is a file-based archive, or collection of file-based assets.  This can be
    a raw directory or a single archive file in one of the supported formats (.tar, .tar.gz, or .zip).
    """

    path: str

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Wrap items in a dict: AssetArchive({"name": FileAsset(path), ...})
  2. If you have a list of (key, value) pairs, convert with dict(pairs)
  3. Handle None by providing a default empty dict

Example fix

// before
archive = AssetArchive([FileAsset("index.js")])
// after
archive = AssetArchive({"index.js": FileAsset("index.js")})
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(assets, dict):
    assets = dict(assets) if isinstance(assets, (list, tuple)) else {}

Type guard

def is_asset_archive_input(v: object) -> bool:
    return isinstance(v, dict)

Try / catch

try:
    archive = AssetArchive(items)
except TypeError as e:
    logging.error("AssetArchive input invalid: %s", e)
    archive = AssetArchive(dict(items))

Prevention

When it happens

Trigger: Calling AssetArchive() with a list, tuple, None, or a non-dict mapping like a plain object.

Common situations: Building an archive from a list of files and forgetting to zip them into a dict, or passing None when a variable is unset.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/3e85995b115281e4. Report an issue: GitHub.