/api/status/ returns JSON serialization error with django-health-check installed #11929

Closed
opened 2025-12-29 21:51:38 +01:00 by adam · 3 comments
Owner

Originally created by @dantte-lp on GitHub (Dec 16, 2025).

NetBox Edition

NetBox Community

NetBox Version

v4.4.8

Python Version

3.12

Steps to Reproduce

  1. Install NetBox 4.4.8
  2. Install django-health-check package (version 3.20.0)
  3. Add health_check to Django's INSTALLED_APPS
  4. Access /api/status/ endpoint

Expected Behavior

The /api/status/ endpoint should return a valid JSON response containing version information for all installed apps.

Observed Behavior

The endpoint returns:

TypeError: Object of type type is not JSON serializable

Root Cause Analysis:

The django-health-check package uses setuptools-scm for versioning. In their health_check/__init__.py:

from health_check import _version
VERSION = _version.VERSION_TUPLE

Due to how setuptools-scm generates _version.py, VERSION_TUPLE is defined as:

VERSION_TUPLE: Tuple[int, int, int] = object  # type placeholder at runtime

At runtime, VERSION_TUPLE is actually <class 'object'> rather than an actual tuple like (3, 20, 0).

The get_installed_apps() function in netbox/utilities/apps.py retrieves this VERSION attribute and attempts to include it in the response dictionary. Since <class 'object'> is not JSON-serializable, the API call fails.

Suggested Fix:

Add a check in get_installed_apps() to skip VERSION values that are neither tuples nor strings:

if version := getattr(app, 'VERSION', getattr(app, '__version__', None)):
    if type(version) is tuple:
        version = '.'.join(str(n) for n in version)
    elif not isinstance(version, str):
        # Skip non-serializable version types
        continue
    installed_apps[app_config.name] = version

This defensive approach ensures that any third-party package with a non-standard VERSION attribute won't break the /api/status/ endpoint.

I have a fix ready and would be happy to submit a PR if this issue is assigned to me.

Originally created by @dantte-lp on GitHub (Dec 16, 2025). ### NetBox Edition NetBox Community ### NetBox Version v4.4.8 ### Python Version 3.12 ### Steps to Reproduce 1. Install NetBox 4.4.8 2. Install `django-health-check` package (version 3.20.0) 3. Add `health_check` to Django's `INSTALLED_APPS` 4. Access `/api/status/` endpoint ### Expected Behavior The `/api/status/` endpoint should return a valid JSON response containing version information for all installed apps. ### Observed Behavior The endpoint returns: ``` TypeError: Object of type type is not JSON serializable ``` **Root Cause Analysis:** The `django-health-check` package uses `setuptools-scm` for versioning. In their `health_check/__init__.py`: ```python from health_check import _version VERSION = _version.VERSION_TUPLE ``` Due to how `setuptools-scm` generates `_version.py`, `VERSION_TUPLE` is defined as: ```python VERSION_TUPLE: Tuple[int, int, int] = object # type placeholder at runtime ``` At runtime, `VERSION_TUPLE` is actually `<class 'object'>` rather than an actual tuple like `(3, 20, 0)`. The `get_installed_apps()` function in `netbox/utilities/apps.py` retrieves this `VERSION` attribute and attempts to include it in the response dictionary. Since `<class 'object'>` is not JSON-serializable, the API call fails. **Suggested Fix:** Add a check in `get_installed_apps()` to skip VERSION values that are neither tuples nor strings: ```python if version := getattr(app, 'VERSION', getattr(app, '__version__', None)): if type(version) is tuple: version = '.'.join(str(n) for n in version) elif not isinstance(version, str): # Skip non-serializable version types continue installed_apps[app_config.name] = version ``` This defensive approach ensures that any third-party package with a non-standard VERSION attribute won't break the `/api/status/` endpoint. I have a fix ready and would be happy to submit a PR if this issue is assigned to me.
adam added the netbox label 2025-12-29 21:51:38 +01:00
adam closed this issue 2025-12-29 21:51:38 +01:00
Author
Owner

@dantte-lp commented on GitHub (Dec 16, 2025):

I would like to volunteer to own this issue. I have already prepared a fix in PR #20994.

@dantte-lp commented on GitHub (Dec 16, 2025): I would like to volunteer to own this issue. I have already prepared a fix in PR #20994.
Author
Owner

@jnovinger commented on GitHub (Dec 19, 2025):

@dantte-lp, from what I can glean from previous conversations around health checks, and django-health-check in particular, is that NetBox does not guarantee to to support it, as discussed in #8831. The final comment in that issue thread is a pointer to a plugin that implements health checks in a NetBox friendly way: https://github.com/netbox-community/netbox-healthcheck-plugin

Having said that, I can imagine that there are potential scenarios where an actual NetBox dependency might do something similar, so providing some defense around this is not an awful idea. Having said that, I'm not sure that just adding a type-check against str is the way I would handle it. Since you've already filed a PR, I'll take that conversation there.

Which brings me to a final point, our contribution process, as documented in CONTRIBUTING.md very clearly states that volunteers should not begin work or file PRs until an issue has been reviewed, accepted, and assigned to them. I will assign this one to you, but please follow our designated process in the future.

@jnovinger commented on GitHub (Dec 19, 2025): @dantte-lp, from what I can glean from previous conversations around health checks, and django-health-check in particular, is that NetBox does not guarantee to to support it, as discussed in #8831. The final comment in that issue thread is a pointer to a plugin that implements health checks in a NetBox friendly way: https://github.com/netbox-community/netbox-healthcheck-plugin Having said that, I can imagine that there are potential scenarios where an actual NetBox dependency might do something similar, so providing some defense around this is not an awful idea. Having said that, I'm not sure that just adding a type-check against `str` is the way I would handle it. Since you've already filed a PR, I'll take that conversation there. Which brings me to a final point, our contribution process, as documented in [CONTRIBUTING.md](https://github.com/netbox-community/netbox/blob/main/CONTRIBUTING.md#arrow_heading_up-submitting-pull-requests) very clearly states that volunteers should not begin work or file PRs until an issue has been reviewed, accepted, and assigned to them. I will assign this one to you, but please follow our designated process in the future.
Author
Owner

@jnovinger commented on GitHub (Dec 19, 2025):

Actually, I'm going to backtrack on this and close it as not-planned. This stems from a bug in django-health-check that is fixed in 3.20.1.

@jnovinger commented on GitHub (Dec 19, 2025): Actually, I'm going to backtrack on this and close it as not-planned. This stems from a bug in django-health-check that is [fixed](https://github.com/revsys/django-health-check/pull/478) in 3.20.1.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#11929