microsoft/semantic-kernel · error · FunctionExecutionException

The `RestApiOperation` instance with id {self.id} is frozen

Error message

The `RestApiOperation` instance with id {self.id} is frozen and cannot be modified.

What it means

RestApiOperation implements a freeze pattern: once `freeze()` is called, the operation and its parameters/request body become immutable. Every property setter calls `_throw_if_frozen()`, which raises FunctionExecutionException if `_is_frozen` is True. This prevents modification of operations after they have been registered/validated, typically after an OpenAPI runner has loaded and prepared them for execution.

Source

Thrown at python/semantic_kernel/connectors/openapi_plugin/models/rest_api_operation.py:90

        self._request_body = request_body
        self._responses = responses
        self._security_requirements = security_requirements
        self._is_frozen = False

    def freeze(self):
        """Make the instance and its components immutable."""
        self._is_frozen = True

        if self.request_body:
            self.request_body.freeze()

        for param in self.parameters:
            param.freeze()

    def _throw_if_frozen(self):
        """Raise an exception if the object is frozen."""
        if self._is_frozen:
            raise FunctionExecutionException(
                f"The `RestApiOperation` instance with id {self.id} is frozen and cannot be modified."
            )

    @property
    def id(self):
        """Get the ID of the operation."""
        return self._id

    @id.setter
    def id(self, value: str):
        self._throw_if_frozen()
        self._id = value

    @property
    def method(self):
        """Get the method of the operation."""
        return self._method

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Create a new RestApiOperation instance (or re-load the spec) instead of mutating a frozen one.
  2. Perform all configuration before the operation is frozen (before the runner prepares/executes it).
  3. Check `operation._is_frozen` before attempting mutation if you share operation handles across code paths.

Example fix

// before
operation.path = "/new-path"  # raises if frozen
// after
# build a new operation or re-load the spec with the desired path
new_op = RestApiOperation(id=operation.id, method=operation.method, path="/new-path", ...)
Defensive patterns

Strategy: type-guard

Validate before calling

def is_frozen(operation) -> bool:
    return getattr(operation, "_is_frozen", False)

Type guard

def is_operation_frozen(op: RestApiOperation) -> bool:
    """Return True if the operation has been frozen and cannot be modified."""
    return op._is_frozen is True

Try / catch

try:
    operation.path = new_path
except FunctionExecutionException as e:
    if "frozen" in str(e):
        # create a new RestApiOperation instead of mutating
        ...

Prevention

When it happens

Trigger: Attempting to set any property (id, method, path, parameters, etc.) on a RestApiOperation after `freeze()` has been called on it. The OpenAPI runner freezes operations during preparation, so any post-load mutation triggers this.

Common situations: Developer loads an OpenAPI spec via the plugin, gets a handle to an operation object, and tries to modify its path or parameters at runtime. Attempting to reuse or reconfigure a frozen operation from a cached runner.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/e56eb4014b7a71e7. Report an issue: GitHub.