Skip to content

[Inference Gateway][Switchyard] Deleting one VM unregisters factories still referenced by live VMs (catalog-visible but 500 Factory-not-found) #1341

Description

@puhuim

Summary

Deleting ANY Switchyard VirtualModel can break inference for OTHER, still-live Switchyard VMs: the surviving VM stays catalog-visible but every inference request answers 500 {"detail": "Factory not found for config hash ..."}.

Tracked internally as NVBug 6563245 (filed 2026-08-05, hit daily by the QA skill-eval suite where VMs are created/destroyed per test).

Root cause

The IGW lifecycle dispatcher (middleware_registry._sdk_vm_to_plugin_vm) builds plugin VirtualModels without mapping the entity id — every on_virtual_model_upserted/on_virtual_model_destroyed hook receives id == "".

nemo_switchyard.middleware keyed its per-VM bookkeeping on that id:

  • on_virtual_model_upserted: VM_CONFIG_MAPPING[virtual_model.id] = hashes -> ALL VMs collapse into the single "" slot; each upsert overwrites the previous VM's entry.
  • on_virtual_model_destroyed: VM_CONFIG_MAPPING.pop(vm_id) pops the shared slot, computes remaining_hashes without the surviving VMs, and unregisters factories they still reference.

Server log capture of the collision (revision 5d4aa25):

07:48:33.483 Registered factory 'nemo-switchyard-random_routing-0c264eb2f00f7d17' for VM 'default/skill-eval-swy-claude-...'
07:48:33.484 Unregistered factory 'nemo-switchyard-random_routing-0c264eb2f00f7d17'   <- destroy of the PREVIOUS VM, 1ms later
             (surviving VM's next request => 500 Factory not found)

Live reproduction (same revision, unfixed)

create race-a (switchyard random_routing)  -> 201
create race-b (identical config)           -> 201
invoke race-b                              -> 200
delete race-a                              -> 204
invoke race-b                              -> 500 "Factory not found for config hash 6e24859f4d219a91 (VM default/race-ctl-b)"

Fix

Key VM_CONFIG_MAPPING by vm_key (workspace/name) — the identity both hooks reliably carry. Two-line change in plugins/nemo-switchyard/src/nemo_switchyard/middleware.py plus regression tests reproducing the production (id-less) VM shape.

With the fix (source deployment on :8090): the same sequence ends invoke race-b -> 200, correctly routed; plugin suite 77 passed; mutation check confirms the new tests fail on the unfixed code.

Note: the SSE double-encoding on /v1/responses for Switchyard VMs is a SEPARATE defect (NVBug 6563029) and is not addressed here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions