apache/beam · error · RuntimeError
Invalid model update: sent many model paths to update, but…
Error message
Invalid model update: sent many model paths to update, but KeyedModelHandler is wrapping a single model.
What it means
update_model_paths on KeyedModelHandler supports updating models only when the handler wraps multiple handlers/cohorts. If it wraps a single model, receiving multiple (or any list-form) model paths is treated as an invalid update and a RuntimeError is raised, since there is no cohort structure to distribute them across.
Solutions
- Pass a single model path (or None) when the KeyedModelHandler wraps one model, matching its single-model mode.
- If multi-path updates are intended, wrap multiple handlers: KeyedModelHandler([KeyedModelHandlerTuple(...), ...]).
- Guard the update callback: check keyed_mh._single_model (or catch RuntimeError) and route single-model updates accordingly.
Example fix
# before keyed = KeyedModelHandler(MyHandler(path)) keyed.update_model_paths(['new_a', 'new_b']) # RuntimeError # after keyed = KeyedModelHandler([ KeyedModelHandlerTuple(MyHandler(path), ['cohort_a']), KeyedModelHandlerTuple(MyHandler(path2), ['cohort_b'])]) keyed.update_model_paths(['new_a', 'new_b'])
Defensive patterns
Strategy: validation
Validate before calling
if getattr(keyed, '_single_model', True) and model_paths and len(model_paths) > 1:
raise ValueError('Single-model KeyedModelHandler cannot accept multiple update paths') Type guard
def supports_multi_path_update(keyed):
return not getattr(keyed, '_single_model', True) Try / catch
try:
keyed.update_model_paths(model_paths)
except RuntimeError as e:
if 'wrapping a single model' in str(e):
keyed.update_model_paths([model_paths[0]])
else:
raise Prevention
- Match the update-path arity to the handler mode: one path for single, many for multi-handler.
- Guard background model-refresh callbacks with a handler-mode check.
- Document whether a pipeline's handler is keyed-single or keyed-multi before enabling auto refresh.
When it happens
Trigger: Calling keyed_mh.update_model_paths(paths) with a list of several paths on a KeyedModelHandler constructed from a single (non-list) handler; background model-refresh hook delivering multi-cohort updates to a single-model handler.
Common situations: Enabling automatic model refresh (model_manager / update_model_paths via a Watch/flush watcher) on a pipeline that later switched to a single unkeyed handler; config driven updates that always pass a list of candidate paths.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Invalid model update, path for
- Cannot make make an unkeyed model handler with pre or…
- Cannot override RemoteModelHandler.load_model, implement…
- Cannot override RemoteModelHandler.run_inference, implement…
- Cannot use an unkeyed model handler with pre or…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/9a53e8c55de62f50.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/ml/inference/base.py:953
def validate_inference_args(self, inference_args: Optional[dict[str, Any]]):
if self._single_model:
return self._unkeyed.validate_inference_args(inference_args)
for mh in self._id_to_mh_map.values():
mh.validate_inference_args(inference_args)
def update_model_paths(
self,
model: Union[ModelT, _ModelHandlerManager],
model_paths: list[KeyModelPathMapping[KeyT]] = None):
# When there are many models, the keyed model handler is responsible for
# reorganizing the model handlers into cohorts and telling the model
# manager to update every cohort's associated model handler. The model
# manager is responsible for performing the updates and tracking which
# updates have already been applied.
if model_paths is None or len(model_paths) == 0 or model is None:
return
if self._single_model:
raise RuntimeError(
'Invalid model update: sent many model paths to '
'update, but KeyedModelHandler is wrapping a single '
'model.')
# Map cohort ids to a dictionary mapping new model paths to the keys that
# were originally in that cohort. We will use this to construct our new
# cohorts.
# cohort_path_mapping will be structured as follows:
# {
# original_cohort_id: {
# 'update/path/1': ['key1FromOriginalCohort', key2FromOriginalCohort'],
# 'update/path/2': ['key3FromOriginalCohort', key4FromOriginalCohort'],
# }
# }
cohort_path_mapping: dict[KeyT, dict[str, list[KeyT]]] = {}
key_modelid_mapping: dict[KeyT, str] = {}
seen_keys = set()
for mp in model_paths:
keys = mp.keysView on GitHub (pinned to 12126d8942)