Summary
plugins/module_utils/rest/response_handler_nd.py classifies HTTP 207 as success
(RETURN_CODE in (200, 201, 202, 204, 207)), so per-item failures inside the response
body are silently ignored. ND uses 207 as the wrapper status for batch interface
operations regardless of whether individual items succeeded or failed.
Reproduction (ND 4.2.1, lab SITE1, 2026-05-27)
POST /api/v1/manage/fabrics/SITE1/switches/<sn>/interfaces with interfaceType: "subInterface"
targeting a trunk-mode parent returns:
HTTP 207
{"results": [{"name": "Port-channel1.999",
"status": "failed",
"message": "Sub-interface can be created only on routed physical or
port-channel interfaces (discovered mode is not routed)
for interface Port-channel1.999[subInterface]"}]}
RestSend / ResponseHandler return this body up to the orchestrator without raising.
Any module hitting batch interface or interface-action endpoints (subinterface, breakout,
fabric_update_group, and likely vpc_pair too) will see "success" while ND actually
rejected every item in the batch — masking real failures and breaking idempotency.
Status string varies by endpoint
- Subinterface POST →
status: "failed" (verified above)
- Breakout action →
status: "error" (per existing memory project_breakout_design.md)
The fix needs to handle both literals.
Suggested fix
In response_handler_nd.py (or the per-verb response strategies under
plugins/module_utils/rest/response_strategies/), treat 207 as success only when no
item in results[] (or equivalent envelope) carries status in ("failed", "error").
When any item fails, propagate an error so RestSend.commit() raises and the
orchestrator's _request() surfaces a clean failure message to the user.
Test plan
Context
Surfaced while scaffolding nd_interface_subinterface_managed against the ND 4.2.1 lab.
Same response shape as project_breakout_design.md flagged earlier, but with a different
status literal — so a fix must handle both.
Summary
plugins/module_utils/rest/response_handler_nd.pyclassifies HTTP 207 as success(
RETURN_CODE in (200, 201, 202, 204, 207)), so per-item failures inside the responsebody are silently ignored. ND uses 207 as the wrapper status for batch interface
operations regardless of whether individual items succeeded or failed.
Reproduction (ND 4.2.1, lab SITE1, 2026-05-27)
POST
/api/v1/manage/fabrics/SITE1/switches/<sn>/interfaceswithinterfaceType: "subInterface"targeting a trunk-mode parent returns:
RestSend/ResponseHandlerreturn this body up to the orchestrator without raising.Any module hitting batch interface or interface-action endpoints (subinterface, breakout,
fabric_update_group, and likely vpc_pair too) will see "success" while ND actually
rejected every item in the batch — masking real failures and breaking idempotency.
Status string varies by endpoint
status: "failed"(verified above)status: "error"(per existing memoryproject_breakout_design.md)The fix needs to handle both literals.
Suggested fix
In
response_handler_nd.py(or the per-verb response strategies underplugins/module_utils/rest/response_strategies/), treat 207 as success only when noitem in
results[](or equivalent envelope) carriesstatus in ("failed", "error").When any item fails, propagate an error so
RestSend.commit()raises and theorchestrator's
_request()surfaces a clean failure message to the user.Test plan
results[].status == "ok"→ successresults[](some ok, somefailed) → raises with the failure messages aggregatedresults[].status == "error"→ raises (covers breakout style)nd_interface_subinterface_managedagainst a trunk-mode parent and assert the module fails with the ND parent-mode message rather than returning successContext
Surfaced while scaffolding
nd_interface_subinterface_managedagainst the ND 4.2.1 lab.Same response shape as
project_breakout_design.mdflagged earlier, but with a differentstatus literal — so a fix must handle both.