Skip to content

Ingest of Device with JSON Custom Field type error #125

@jasonhollifield

Description

@jasonhollifield

Diode NetBox Plugin version

v1.2.1

NetBox version

v4.2.9

Diode version

v1.4.0

Diode SDK type

diode-sdk-python

Diode SDK version

1.2.0

Steps to reproduce

Steps to Reproduce

  1. Set up the environment:

    • Install the netboxlabs-diode SDK
    • Run a Diode server at grpc://localhost:8080/diode connected to a netbox instance with the diode plugin
  2. Create a device with a custom field containing JSON data.

Minimal Example Code

from netboxlabs.diode.sdk import DiodeClient
from netboxlabs.diode.sdk.ingester import Device, DeviceType, Entity, CustomFieldValue
import json

with DiodeClient(
    target="grpc://localhost:8080/diode",
    app_name="test-app",
    app_version="0.0.1",
) as client:
    # Create JSON custom field data
    json_data = [{"ip": "192.168.1.1", "peer_group": "test-group"}]

    # Create custom field with JSON value
    custom_field = CustomFieldValue(
        json=json.dumps(json_data)
    )

    # Create device with custom field
    device = Device(
        name="test-device",
        device_type=DeviceType(
            model="test-model",
            manufacturer="test-manufacturer"
        ),
        site="test-site",
        role="switch",
        custom_fields={
            "bgp_neighbors": custom_field  # This will fail
        }
    )

    # Ingest the device
    entities = [Entity(device=device)]
    response = client.ingest(entities=entities)
  1. View netbox instance logs to observe the error

Workaround

Prefix the custom field name with an underscore to avoid the error:

custom_fields={
    "_bgp_neighbors": custom_field
}

I found this by following the trace to matcher.py and the _fingerprint_all function

def _fingerprint_all(data: dict, object_type: str|None = None) -> str:
    """
    Returns a fingerprint of the data based on all fields.

    Data should be a (flattened) dictionary of field values.
    This ignores any fields that start with an underscore.
    """
    if data is None:
        return None

    values = ["object_type", object_type]
    for k, v in sorted(data.items()):
        if k.startswith("_"):
            continue
        values.append(k)
        if isinstance(v, list | tuple):
            values.extend(sorted(v))
        elif isinstance(v, dict):
            values.append(_fingerprint_all(v))
        else:
            values.append(v)

    return hash(tuple(values))

Expected behavior

The device should be ingested successfully with the custom field containing JSON data.

Observed behavior

Error Output

[31/Jul/2025 23:47:42] "POST /api/plugins/diode/generate-diff/ HTTP/1.1" 500 151
Unexpected error generating changeset: '<' not supported between instances of 'dict' and 'dict'
Traceback (most recent call last):
  File ".../views.py", line 68, in post
    return self._post(request, *args, **kwargs)
  File ".../views.py", line 98, in _post
    result = generate_changeset(original_entity_data, object_type)
  File ".../differ.py", line 166, in generate_changeset
    return _generate_changeset(entity, object_type)
  File ".../differ.py", line 179, in _generate_changeset
    entities = transform_proto_json(entity, object_type, SUPPORTED_MODELS)
  File ".../transformer.py", line 101, in transform_proto_json
    deduplicated = _fingerprint_dedupe(entities)
  File ".../transformer.py", line 412, in _fingerprint_dedupe
    fps = fingerprints(entity, entity['_object_type'])
  File ".../matcher.py", line 833, in fingerprints
    fp = _fingerprint_all(data, object_type)
  File ".../matcher.py", line 810, in _fingerprint_all
    values.append(_fingerprint_all(v))
  File ".../matcher.py", line 808, in _fingerprint_all
    values.extend(sorted(v))
TypeError: '<' not supported between instances of 'dict' and 'dict'

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstatus: needs triageThis issue is awaiting triage by a maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions