pulumi/pulumi · error · TypeError

Expected opts2 to be a InvokeOptions instance

Error message

Expected opts2 to be a InvokeOptions instance

What it means

Same validation as opts1, applied to the second InvokeOptions argument of the merge helper. The second options object supplies overrides (parent, provider, version); if it is not an InvokeOptions instance a TypeError is raised.

Source

Thrown at sdk/python/lib/pulumi/invoke.py:114

           from `opts1`.

        3. For the purposes of merging `depends_on` is always treated
           as collections, even if only a single value was provided.

        4. Attributes with value 'None' will not be copied over.

        This method can be called either as static-method like `InvokeOptions.merge(opts1, opts2)`
        or as an instance-method like `opts1.merge(opts2)`.  The former is useful for cases where
        `opts1` may be `None` so the caller does not need to check for this case.
        """
        opts1 = InvokeOptions() if opts1 is None else opts1
        opts2 = InvokeOptions() if opts2 is None else opts2

        if not isinstance(opts1, InvokeOptions):
            raise TypeError("Expected opts1 to be a InvokeOptions instance")

        if not isinstance(opts2, InvokeOptions):
            raise TypeError("Expected opts2 to be a InvokeOptions instance")

        dest = copy.copy(opts1)
        source = opts2

        dest.parent = dest.parent if source.parent is None else source.parent
        dest.provider = dest.provider if source.provider is None else source.provider
        dest.plugin_download_url = (
            dest.plugin_download_url
            if source.plugin_download_url is None
            else source.plugin_download_url
        )
        dest.version = dest.version if source.version is None else source.version

        return dest


class InvokeOutputOptions(InvokeOptions):
    """

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Wrap the value in InvokeOptions(...) before merging
  2. Convert ResourceOptions fields into InvokeOptions equivalents
  3. Fix argument order if an options object landed in the wrong position
  4. Update test doubles to be real InvokeOptions instances

Example fix

// before
merged = merge_invoke_opts(opts1, {'parent': p})
// after
merged = merge_invoke_opts(opts1, pulumi.InvokeOptions(parent=p))
Defensive patterns

Strategy: type-guard

Validate before calling

if opts2 is not None and not isinstance(opts2, pulumi.InvokeOptions):
    raise TypeError('opts2 must be InvokeOptions')

Type guard

def is_invoke_options2(o) -> bool:
    return o is None or isinstance(o, pulumi.InvokeOptions)

Try / catch

try:
    merged = merge_invoke_opts(opts1, opts2)
except TypeError as e:
    if 'opts2' in str(e):
        opts2 = pulumi.InvokeOptions()
        merged = merge_invoke_opts(opts1, opts2)

Prevention

When it happens

Trigger: Passing a ResourceOptions, InvokeOutputOptions, dict, or string as opts2 to the invoke options merge helper.

Common situations: Swapping argument order or passing resource-style options in invoke helpers; refactors where a function parameter changed type; tests passing mocks that aren't InvokeOptions.

Related errors


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