Updating a Cable Termination over the API results in a missing connection/trace #9341

Closed
opened 2025-12-29 20:48:44 +01:00 by adam · 11 comments
Owner

Originally created by @Hedius on GitHub (Mar 9, 2024).

Deployment Type

Self-hosted

NetBox Version

v3.7.3

Python Version

3.11

Steps to Reproduce

I only was able to identify issue #14200, #14137 (closed/rejected) as a similar problem.

The following steps are made for a clean empty netbox installation.

Initial setup

  1. Create a manufacturer (HPE in this case).

  2. Create a device type for that one. (ProLiant DL360 Gen11 in this case).

  3. Create a device/VM role (Server in this case).

  4. Create a site (DC1).

  5. Create 2 Servers with that role, site and type. (server001, server002).
    image

  6. Assign an interface (eth0 in this case) to both servers.

Create a cable between both

{
  "a_terminations": [
    {
      "object_type": "dcim.interface",
      "object_id": 1
    }
  ],
  "b_terminations": [
    {
      "object_type": "dcim.interface",
      "object_id": 2
    }
  ],
  "status": "connected"
}
curl -X 'POST' \
  'http://127.0.0.1:8000/api/dcim/cables/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "a_terminations": [
    {
      "object_type": "dcim.interface",
      "object_id": 1
    }
  ],
  "b_terminations": [
    {
      "object_type": "dcim.interface",
      "object_id": 2
    }
  ],
  "status": "connected"
}'

After this POST the interfaces are cabled and you can see the connection and link peers. 2 Terminations with the IDs (1,2) exist after this.
image

image

Add more interfaces to servers and change the cable in the GUI.

  1. Add eth1 to server002 (same config.
  2. Change the B termination for the cable from eth0 to eth1.
    image

The old termination is deleted, replaced with a new one, the connection is updated and you can trace the cable.
image

Now over the API, Delete termination B

  1. There is a similar issue from december: #14137 (got closed, though)
  2. The person there updated the termination by patching the cable over api/dcim/cables.
  3. Both the changelog screenshot from above and @jeremystretch ´s comment show that the correct way is to delete the termination and create a new one.
  4. So delete the termination for cable 1 (server002 -> eth1) with a DELETE to /api/dcim/cable-terminations/3/
  5. curl -X 'DELETE' 'http://127.0.0.1:8000/api/dcim/cable-terminations/3/'

Create a new B termination for server002 -> eth0

post data

{
  "cable": 1,
  "cable_end": "B",
  "termination_type": "dcim.interface",
  "termination_id": 2
}
curl -X 'POST' \
  'http://127.0.0.1:8000/api/dcim/cable-terminations/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "cable": 1,
  "cable_end": "B",
  "termination_type": "dcim.interface",
  "termination_id": 2
}'

image

Cable and terminations have correct data (Skip this... issue after this one :) )

Data for both terminations and the cable looks correct.... nothing special.

{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "url": "http://127.0.0.1:8000/api/dcim/cable-terminations/1/",
            "display": "Cable #1 to eth0",
            "cable": 1,
            "cable_end": "A",
            "termination_type": "dcim.interface",
            "termination_id": 1,
            "termination": {
                "id": 1,
                "url": "http://127.0.0.1:8000/api/dcim/interfaces/1/",
                "display": "eth0",
                "device": {
                    "id": 1,
                    "url": "http://127.0.0.1:8000/api/dcim/devices/1/",
                    "display": "server001",
                    "name": "server001"
                },
                "name": "eth0",
                "cable": 1,
                "_occupied": true
            },
            "created": "2024-03-09T18:12:52.063515Z",
            "last_updated": "2024-03-09T18:12:52.063527Z"
        },
        {
            "id": 4,
            "url": "http://127.0.0.1:8000/api/dcim/cable-terminations/4/",
            "display": "Cable #1 to eth0",
            "cable": 1,
            "cable_end": "B",
            "termination_type": "dcim.interface",
            "termination_id": 2,
            "termination": {
                "id": 2,
                "url": "http://127.0.0.1:8000/api/dcim/interfaces/2/",
                "display": "eth0",
                "device": {
                    "id": 2,
                    "url": "http://127.0.0.1:8000/api/dcim/devices/2/",
                    "display": "server002",
                    "name": "server002"
                },
                "name": "eth0",
                "cable": 1,
                "_occupied": true
            },
            "created": "2024-03-09T18:33:25.250711Z",
            "last_updated": "2024-03-09T18:33:25.250729Z"
        }
    ]
}
{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "url": "http://127.0.0.1:8000/api/dcim/cables/1/",
            "display": "#1",
            "type": "",
            "a_terminations": [
                {
                    "object_type": "dcim.interface",
                    "object_id": 1,
                    "object": {
                        "id": 1,
                        "url": "http://127.0.0.1:8000/api/dcim/interfaces/1/",
                        "display": "eth0",
                        "device": {
                            "id": 1,
                            "url": "http://127.0.0.1:8000/api/dcim/devices/1/",
                            "display": "server001",
                            "name": "server001"
                        },
                        "name": "eth0",
                        "cable": 1,
                        "_occupied": true
                    }
                }
            ],
            "b_terminations": [
                {
                    "object_type": "dcim.interface",
                    "object_id": 2,
                    "object": {
                        "id": 2,
                        "url": "http://127.0.0.1:8000/api/dcim/interfaces/2/",
                        "display": "eth0",
                        "device": {
                            "id": 2,
                            "url": "http://127.0.0.1:8000/api/dcim/devices/2/",
                            "display": "server002",
                            "name": "server002"
                        },
                        "name": "eth0",
                        "cable": 1,
                        "_occupied": true
                    }
                }
            ],
            "status": {
                "value": "connected",
                "label": "Connected"
            },
            "tenant": null,
            "label": "",
            "color": "",
            "length": null,
            "length_unit": null,
            "description": "",
            "comments": "",
            "tags": [],
            "custom_fields": {},
            "created": "2024-03-09T18:12:52.049438Z",
            "last_updated": "2024-03-09T18:19:21.528022Z"
        }
    ]
}

Connection is missing

However, in the server -> interfaces view, the connection is not listed anymore.
image

And you can no longer trace the cable.
image

image

Tracing over the API is also not possible at this point.

Summary

Correct me if I did smth wrong... But GUI actions cause the same actions and you suggested in #14200 to do it like this. Is this the correct way for updating cables?

Expected Behavior

  1. A cable should have a connection after deleting/creating its terminations over the API. (See the description from above.)

Observed Behavior

  1. After deleting and creating a new termination for a cable, it does not have a connection anymore.
    Both terminations are interfaces. Furthermore, you cannot trace the path anymore.
Originally created by @Hedius on GitHub (Mar 9, 2024). ### Deployment Type Self-hosted ### NetBox Version v3.7.3 ### Python Version 3.11 ### Steps to Reproduce I only was able to identify issue #14200, #14137 (closed/rejected) as a similar problem. The following steps are made for a clean empty netbox installation. # Initial setup 1. Create a manufacturer (HPE in this case). 2. Create a device type for that one. (ProLiant DL360 Gen11 in this case). 3. Create a device/VM role (Server in this case). 4. Create a site (DC1). 5. Create 2 Servers with that role, site and type. (server001, server002). ![image](https://github.com/netbox-community/netbox/assets/14820882/37591ab7-681d-4288-849f-b09644e8d007) 6. Assign an interface (eth0 in this case) to both servers. # Create a cable between both ```json { "a_terminations": [ { "object_type": "dcim.interface", "object_id": 1 } ], "b_terminations": [ { "object_type": "dcim.interface", "object_id": 2 } ], "status": "connected" } ``` ```sh curl -X 'POST' \ 'http://127.0.0.1:8000/api/dcim/cables/' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "a_terminations": [ { "object_type": "dcim.interface", "object_id": 1 } ], "b_terminations": [ { "object_type": "dcim.interface", "object_id": 2 } ], "status": "connected" }' ``` After this POST the interfaces are cabled and you can see the connection and link peers. 2 Terminations with the IDs (1,2) exist after this. ![image](https://github.com/netbox-community/netbox/assets/14820882/9f7dcb00-76de-4166-9778-0ebf1c445f24) ![image](https://github.com/netbox-community/netbox/assets/14820882/1aaa3808-af66-4da1-bb9f-2fc908dd45f2) # Add more interfaces to servers and change the cable in the GUI. 1. Add eth1 to server002 (same config. 2. Change the B termination for the cable from eth0 to eth1. ![image](https://github.com/netbox-community/netbox/assets/14820882/750f8c8e-c2ab-4ed0-9afb-4bde1fdef479) The old termination is deleted, replaced with a new one, the connection is updated and you can trace the cable. ![image](https://github.com/netbox-community/netbox/assets/14820882/9d60a031-2ccf-492c-85e7-e2b33322cc23) # Now over the API, Delete termination B 1. There is a similar issue from december: #14137 (got closed, though) 2. The person there updated the termination by patching the cable over `api/dcim/cables`. 3. Both the changelog screenshot from above and @jeremystretch ´s comment show that the correct way is to delete the termination and create a new one. 4. So delete the termination for cable 1 (server002 -> eth1) with a DELETE to `/api/dcim/cable-terminations/3/` 5. `curl -X 'DELETE' 'http://127.0.0.1:8000/api/dcim/cable-terminations/3/'` # Create a new B termination for server002 -> eth0 post data ```json { "cable": 1, "cable_end": "B", "termination_type": "dcim.interface", "termination_id": 2 } ``` ```sh curl -X 'POST' \ 'http://127.0.0.1:8000/api/dcim/cable-terminations/' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "cable": 1, "cable_end": "B", "termination_type": "dcim.interface", "termination_id": 2 }' ``` ![image](https://github.com/netbox-community/netbox/assets/14820882/606ff234-535c-4fdf-acf8-4f487e3b84e0) # Cable and terminations have correct data (Skip this... issue after this one :) ) Data for both terminations and the cable looks correct.... nothing special. ```json { "count": 2, "next": null, "previous": null, "results": [ { "id": 1, "url": "http://127.0.0.1:8000/api/dcim/cable-terminations/1/", "display": "Cable #1 to eth0", "cable": 1, "cable_end": "A", "termination_type": "dcim.interface", "termination_id": 1, "termination": { "id": 1, "url": "http://127.0.0.1:8000/api/dcim/interfaces/1/", "display": "eth0", "device": { "id": 1, "url": "http://127.0.0.1:8000/api/dcim/devices/1/", "display": "server001", "name": "server001" }, "name": "eth0", "cable": 1, "_occupied": true }, "created": "2024-03-09T18:12:52.063515Z", "last_updated": "2024-03-09T18:12:52.063527Z" }, { "id": 4, "url": "http://127.0.0.1:8000/api/dcim/cable-terminations/4/", "display": "Cable #1 to eth0", "cable": 1, "cable_end": "B", "termination_type": "dcim.interface", "termination_id": 2, "termination": { "id": 2, "url": "http://127.0.0.1:8000/api/dcim/interfaces/2/", "display": "eth0", "device": { "id": 2, "url": "http://127.0.0.1:8000/api/dcim/devices/2/", "display": "server002", "name": "server002" }, "name": "eth0", "cable": 1, "_occupied": true }, "created": "2024-03-09T18:33:25.250711Z", "last_updated": "2024-03-09T18:33:25.250729Z" } ] } ``` ```json { "count": 1, "next": null, "previous": null, "results": [ { "id": 1, "url": "http://127.0.0.1:8000/api/dcim/cables/1/", "display": "#1", "type": "", "a_terminations": [ { "object_type": "dcim.interface", "object_id": 1, "object": { "id": 1, "url": "http://127.0.0.1:8000/api/dcim/interfaces/1/", "display": "eth0", "device": { "id": 1, "url": "http://127.0.0.1:8000/api/dcim/devices/1/", "display": "server001", "name": "server001" }, "name": "eth0", "cable": 1, "_occupied": true } } ], "b_terminations": [ { "object_type": "dcim.interface", "object_id": 2, "object": { "id": 2, "url": "http://127.0.0.1:8000/api/dcim/interfaces/2/", "display": "eth0", "device": { "id": 2, "url": "http://127.0.0.1:8000/api/dcim/devices/2/", "display": "server002", "name": "server002" }, "name": "eth0", "cable": 1, "_occupied": true } } ], "status": { "value": "connected", "label": "Connected" }, "tenant": null, "label": "", "color": "", "length": null, "length_unit": null, "description": "", "comments": "", "tags": [], "custom_fields": {}, "created": "2024-03-09T18:12:52.049438Z", "last_updated": "2024-03-09T18:19:21.528022Z" } ] } ``` # Connection is missing However, in the server -> interfaces view, the connection is not listed anymore. ![image](https://github.com/netbox-community/netbox/assets/14820882/7ff844ed-a4ec-4a43-a601-bc4f1740062d) And you can no longer trace the cable. ![image](https://github.com/netbox-community/netbox/assets/14820882/77f0e6d7-de98-48bd-bd8f-f7b66663040a) ![image](https://github.com/netbox-community/netbox/assets/14820882/23ed1157-7656-4dc9-b587-a7f20ae86521) Tracing over the API is also not possible at this point. # Summary Correct me if I did smth wrong... But GUI actions cause the same actions and you suggested in #14200 to do it like this. Is this the correct way for updating cables? ### Expected Behavior 1. A cable should have a connection after deleting/creating its terminations over the API. (See the description from above.) ### Observed Behavior 1. After deleting and creating a new termination for a cable, it does not have a connection anymore. Both terminations are interfaces. Furthermore, you cannot trace the path anymore.
adam added the type: bugtopic: cabling labels 2025-12-29 20:48:44 +01:00
adam closed this issue 2025-12-29 20:48:44 +01:00
Author
Owner

@Hedius commented on GitHub (Mar 9, 2024):

Correction, ignore the edit exception part. Duplicate to: #11460
Removed it from the report.

I actually meant to reference #14137 before.

@Hedius commented on GitHub (Mar 9, 2024): Correction, ignore the edit exception part. Duplicate to: #11460 Removed it from the report. I actually meant to reference #14137 before.
Author
Owner

@jeffgdotorg commented on GitHub (Apr 2, 2024):

Thank you for opening a bug report and for taking the time to provide detailed steps to reproduce on a pristine system.

I was unable to reproduce the reported behavior on NetBox v3.7.4. Maybe this means we fixed the problem you're reporting in the course of doing other work. Please re-confirm the reported behavior on the current stable release and adjust your post above as necessary.

@jeffgdotorg commented on GitHub (Apr 2, 2024): Thank you for opening a bug report and for taking the time to provide detailed steps to reproduce on a pristine system. I was unable to reproduce the reported behavior on NetBox v3.7.4. Maybe this means we fixed the problem you're reporting in the course of doing other work. Please re-confirm the reported behavior on the current stable release and adjust your post above as necessary.
Author
Owner

@Hedius commented on GitHub (Apr 2, 2024):

Hi, thank you for your answer and for looking into it. I will redo my script on stable later this week.

@Hedius commented on GitHub (Apr 2, 2024): Hi, thank you for your answer and for looking into it. I will redo my script on stable later this week.
Author
Owner

@Hedius commented on GitHub (Apr 6, 2024):

Hello I performed the same steps on NetBox 3.7,5 and I have the same issue again.

I took a cable. Deleted 1 termination over the API, created a new one and ended up with a cable without a connection as described above...

The cable exists with both terminations, but http://127.0.0.1:8000/dcim/interface-connections/ does not show any connections.

netbox=# select * from dcim_cable;
            created            |         last_updated         | custom_field_data | id | type |  status   | label | color | length | length_unit | _abs_length | tenant_id | comments | description 
-------------------------------+------------------------------+-------------------+----+------+-----------+-------+-------+--------+-------------+-------------+-----------+----------+-------------
 2024-04-06 20:05:42.600335+00 | 2024-04-06 20:05:42.60035+00 | {}                |  2 |      | connected |       |       |        |             |             |           |          | 
netbox=# select * from dcim_cabletermination;
 id | cable_end | termination_id | cable_id | termination_type_id | _device_id | _rack_id | _location_id | _site_id |            created            |         last_updated          
----+-----------+----------------+----------+---------------------+------------+----------+--------------+----------+-------------------------------+-------------------------------
  3 | A         |              1 |        2 |                  42 |          1 |          |              |        1 | 2024-04-06 20:05:42.622425+00 | 2024-04-06 20:05:42.622436+00
  5 | B         |              2 |        2 |                  42 |          3 |          |              |        1 | 2024-04-06 20:12:45.830316+00 | 2024-04-06 20:12:45.830331+00
netbox=# select * from dcim_cablepath;
 id |   _nodes    | is_active | is_split |           path           | is_complete 
----+-------------+-----------+----------+--------------------------+-------------
  3 | {42:1,29:2} | t         | f        | [["42:1"], ["29:2"], []] | f

The cable path only contains the A-Termination and the cable. The B-Termination is missing.

What I did is:

  1. Create a cable with 2 terminations
  2. Delete the B-Termination over the API
  3. Create it again over the API ( as described above)

I looked at the signals of dcim for CablePaths and updates are triggered in different cases (dcim/signals.py):

  1. If I create or update a cable (Editing a cable in the gui triggers this signal) (trace_path is the signa)
  2. If I delete a termination or delete a cable.

So from that posting a cable termination to /api/cable-terminations will never trigger an update of a cable path. (Therefore, no path in the table.... Also verified that the logic does not get triggered with break points.)

Different take. (While in the referenced issue it was said that deleting/creating new cable terminations is the correct way, I gonna try now updating the cable directly with a PATCH to /api/dcim/cables/x/, because updating a termination cannot trigger the trace_path signal?

Before me changing the endpoints the path is documented correctly after creating the cable:

netbox=# select * from dcim_cablepath;
 id |      _nodes      | is_active | is_split |              path              | is_complete 
----+------------------+-----------+----------+--------------------------------+-------------
  9 | {42:1,29:3,42:2} | t         | f        | [["42:1"], ["29:3"], ["42:2"]] | t
 10 | {42:2,29:3,42:1} | t         | f        | [["42:2"], ["29:3"], ["42:1"]] | t

Updated cable the B termination of cable 3 from interface 2 to 3 with a PATCH to /api/dcim/cables/3/

Data:

{
  "b_terminations": [
    {
      "object_type": "dcim.interface",
      "object_id": 3
    }
  ]
}

This clearly seems to be incorrect though:

netbox=# select * from dcim_cablepath;
 id |        _nodes         | is_active | is_split |                  path                  | is_complete 
----+-----------------------+-----------+----------+----------------------------------------+-------------
  9 | {42:1,29:3}           | t         | f        | [["42:1"], ["29:3"], []]               | f
 11 | {42:1,29:3,42:3}      | t         | f        | [["42:1"], ["29:3"], ["42:3"]]         | t
 12 | {42:2,29:3,42:1,42:3} | t         | f        | [["42:2"], ["29:3"], ["42:1", "42:3"]] | t

It does update the terminations now and a Path from A to B is created.

image

The B-Termination is updated correctly, but old B-Termination shows now 2 paths. (Instead of the new one showing one only to the A-Temrination)

I am lost now...

@jeffgdotorg Can you please explain how you updated the termination over the API? Did you update the cable or did you delete/create the terminations?

@Hedius commented on GitHub (Apr 6, 2024): Hello I performed the same steps on NetBox 3.7,5 and I have the same issue again. I took a cable. Deleted 1 termination over the API, created a new one and ended up with a cable without a connection as described above... The cable exists with both terminations, but http://127.0.0.1:8000/dcim/interface-connections/ does not show any connections. ``` netbox=# select * from dcim_cable; created | last_updated | custom_field_data | id | type | status | label | color | length | length_unit | _abs_length | tenant_id | comments | description -------------------------------+------------------------------+-------------------+----+------+-----------+-------+-------+--------+-------------+-------------+-----------+----------+------------- 2024-04-06 20:05:42.600335+00 | 2024-04-06 20:05:42.60035+00 | {} | 2 | | connected | | | | | | | | ``` ``` netbox=# select * from dcim_cabletermination; id | cable_end | termination_id | cable_id | termination_type_id | _device_id | _rack_id | _location_id | _site_id | created | last_updated ----+-----------+----------------+----------+---------------------+------------+----------+--------------+----------+-------------------------------+------------------------------- 3 | A | 1 | 2 | 42 | 1 | | | 1 | 2024-04-06 20:05:42.622425+00 | 2024-04-06 20:05:42.622436+00 5 | B | 2 | 2 | 42 | 3 | | | 1 | 2024-04-06 20:12:45.830316+00 | 2024-04-06 20:12:45.830331+00 ``` ``` netbox=# select * from dcim_cablepath; id | _nodes | is_active | is_split | path | is_complete ----+-------------+-----------+----------+--------------------------+------------- 3 | {42:1,29:2} | t | f | [["42:1"], ["29:2"], []] | f ``` The cable path only contains the A-Termination and the cable. The B-Termination is missing. What I did is: 1. Create a cable with 2 terminations 2. Delete the B-Termination over the API 3. Create it again over the API ( as described above) I looked at the signals of dcim for CablePaths and updates are triggered in different cases (dcim/signals.py): 1. If I create or update a cable (Editing a cable in the gui triggers this signal) (trace_path is the signa) 2. If I delete a termination or delete a cable. So from that posting a cable termination to `/api/cable-terminations` will never trigger an update of a cable path. (Therefore, no path in the table.... Also verified that the logic does not get triggered with break points.) Different take. (While in the referenced issue it was said that deleting/creating new cable terminations is the correct way, I gonna try now updating the cable directly with a PATCH to /api/dcim/cables/x/, because updating a termination cannot trigger the trace_path signal? Before me changing the endpoints the path is documented correctly after creating the cable: ``` netbox=# select * from dcim_cablepath; id | _nodes | is_active | is_split | path | is_complete ----+------------------+-----------+----------+--------------------------------+------------- 9 | {42:1,29:3,42:2} | t | f | [["42:1"], ["29:3"], ["42:2"]] | t 10 | {42:2,29:3,42:1} | t | f | [["42:2"], ["29:3"], ["42:1"]] | t ``` Updated cable the B termination of cable 3 from interface 2 to 3 with a PATCH to /api/dcim/cables/3/ Data: ``` { "b_terminations": [ { "object_type": "dcim.interface", "object_id": 3 } ] } ``` This clearly seems to be incorrect though: ``` netbox=# select * from dcim_cablepath; id | _nodes | is_active | is_split | path | is_complete ----+-----------------------+-----------+----------+----------------------------------------+------------- 9 | {42:1,29:3} | t | f | [["42:1"], ["29:3"], []] | f 11 | {42:1,29:3,42:3} | t | f | [["42:1"], ["29:3"], ["42:3"]] | t 12 | {42:2,29:3,42:1,42:3} | t | f | [["42:2"], ["29:3"], ["42:1", "42:3"]] | t ``` It does update the terminations now and a Path from A to B is created. ![image](https://github.com/netbox-community/netbox/assets/14820882/a0fe8b77-6f69-4927-bd44-886a5619dbc7) The B-Termination is updated correctly, but old B-Termination shows now 2 paths. (Instead of the new one showing one only to the A-Temrination) I am lost now... @jeffgdotorg Can you please explain how you updated the termination over the API? Did you update the cable or did you delete/create the terminations?
Author
Owner

@Hedius commented on GitHub (Apr 6, 2024):

For reference: https://github.com/netbox-community/netbox/blob/develop/netbox/dcim/signals.py#L75 is the cable path logic, but I can only see it getting triggered if you use /api/dcim/cables

Jeremy made clear that you should not do this: https://github.com/netbox-community/netbox/issues/14137#issuecomment-1841141282

But posting a termination cannot trigger the trace_path logic. It is only triggered at b7668fbfc3/netbox/dcim/models/cables.py (L240) (cable modifications)

Correct me please if I am wrong here.
I have had the idea to open a PR and insert sending the trace_path signal in the cable termination save method, but this seems incorrect, because then trace paths would be triggered several times per cable modification/creation

@Hedius commented on GitHub (Apr 6, 2024): For reference: https://github.com/netbox-community/netbox/blob/develop/netbox/dcim/signals.py#L75 is the cable path logic, but I can only see it getting triggered if you use /api/dcim/cables Jeremy made clear that you should not do this: https://github.com/netbox-community/netbox/issues/14137#issuecomment-1841141282 But posting a termination cannot trigger the trace_path logic. It is only triggered at https://github.com/netbox-community/netbox/blob/b7668fbfc3a81abf2c6a8ace98047647fd9244c9/netbox/dcim/models/cables.py#L240 (cable modifications) Correct me please if I am wrong here. I have had the idea to open a PR and insert sending the trace_path signal in the cable termination save method, but this seems incorrect, because then trace paths would be triggered several times per cable modification/creation
Author
Owner

@bsampaio commented on GitHub (Aug 14, 2024):

Hi!
I'm really looking forward to that fix. Thanks @arthanson for the effort.
I'm currently facing the same issue.

@bsampaio commented on GitHub (Aug 14, 2024): Hi! I'm really looking forward to that fix. Thanks @arthanson for the effort. I'm currently facing the same issue.
Author
Owner

@github-actions[bot] commented on GitHub (Apr 24, 2025):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.

@github-actions[bot] commented on GitHub (Apr 24, 2025): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/main/CONTRIBUTING.md).
Author
Owner

@jeremystretch commented on GitHub (Sep 4, 2025):

Following up on this rather dated bug report.

Jeremy made clear that you should not do this: https://github.com/netbox-community/netbox/issues/14137#issuecomment-1841141282

This comment is on an issue concerning NetBox v3.6. On the current NetBox release (v4.4), modifying a cable's terminations via the REST API is supported.

Deleting the B terminations from a cable:

curl -X PATCH \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json; indent=4" \
http://netbox:8000/api/dcim/cables/145/ \
--data '{
  "b_terminations": []
}'

Setting a new B termination:

curl -X PATCH \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json; indent=4" \
http://netbox:8000/api/dcim/cables/145/ \
--data '{
  "b_terminations": [
    {
      "object_type": "dcim.interface",
      "object_id": 1677
    }
  ]
}'

This approach ensures that the cable paths in either direction are updated appropriately. Updating cable terminations directly via the /api/dim/cable-terminations/ REST API endpoint does not recompute the paths, because the trace_paths signal is emitted only by Cable.save().

We might consider limiting the mutability of cable terminations via the dedicated endpoint to avoid confusion, but that's another discussion, and would result in a breaking change which must be explored.

@jeremystretch commented on GitHub (Sep 4, 2025): Following up on this rather dated bug report. > Jeremy made clear that you should not do this: https://github.com/netbox-community/netbox/issues/14137#issuecomment-1841141282 This comment is on an issue concerning NetBox v3.6. On the current NetBox release (v4.4), modifying a cable's terminations via the REST API is supported. Deleting the B terminations from a cable: ``` curl -X PATCH \ -H "Authorization: Token $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json; indent=4" \ http://netbox:8000/api/dcim/cables/145/ \ --data '{ "b_terminations": [] }' ``` Setting a new B termination: ``` curl -X PATCH \ -H "Authorization: Token $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json; indent=4" \ http://netbox:8000/api/dcim/cables/145/ \ --data '{ "b_terminations": [ { "object_type": "dcim.interface", "object_id": 1677 } ] }' ``` This approach ensures that the cable paths in either direction are updated appropriately. Updating cable terminations directly via the `/api/dim/cable-terminations/` REST API endpoint does not recompute the paths, because the `trace_paths` signal is emitted only by `Cable.save()`. We might consider limiting the mutability of cable terminations via the dedicated endpoint to avoid confusion, but that's another discussion, and would result in a breaking change which must be explored.
Author
Owner

@jeremystretch commented on GitHub (Sep 8, 2025):

We might consider limiting the mutability of cable terminations via the dedicated endpoint to avoid confusion, but that's another discussion, and would result in a breaking change which must be explored.

I've opened FR #20295 to propose this change.

@jeremystretch commented on GitHub (Sep 8, 2025): > We might consider limiting the mutability of cable terminations via the dedicated endpoint to avoid confusion, but that's another discussion, and would result in a breaking change which must be explored. I've opened FR #20295 to propose this change.
Author
Owner

@jeremystretch commented on GitHub (Sep 11, 2025):

I'm going to close this issue as we've decided to make the cable terminations endpoint read-only per #20295, which will resolve this bug indirectly. Users are advised to modify cable terminations via the cables endpoint at /api/dcim/cables/ to avoid the bug captured here.

@jeremystretch commented on GitHub (Sep 11, 2025): I'm going to close this issue as we've decided to make the cable terminations endpoint read-only per #20295, which will resolve this bug indirectly. Users are advised to modify cable terminations via the cables endpoint at `/api/dcim/cables/` to avoid the bug captured here.
Author
Owner

@Hedius commented on GitHub (Sep 12, 2025):

Hi, thank you for your answer on the issue. Will change my setup to no longer use that endpoint.

@Hedius commented on GitHub (Sep 12, 2025): Hi, thank you for your answer on the issue. Will change my setup to no longer use that endpoint.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#9341