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
- Create a new RestApiOperation instance (or re-load the spec) instead of mutating a frozen one.
- Perform all configuration before the operation is frozen (before the runner prepares/executes it).
- 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
- Treat loaded RestApiOperation instances as immutable after the runner prepares them.
- Perform all configuration before calling freeze() or before runner execution.
- Check _is_frozen before mutating if operation handles are shared.
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
- No argument is provided for the `{parameter.name}` required
- Error building the URL for the operation {self.id}: {e!s}
- The operation path resolves to '{request.scheme}://{request.
- The operation path resolves to '{request.path}', which is ou
- No argument provided for the '{variable_name}' server variab
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/e56eb4014b7a71e7.
Report an issue: GitHub.