[PR #20592] [MERGED] Fixes #20587: Handle stale ContentTypes in has_feature() #15976

Closed
opened 2025-12-30 00:25:07 +01:00 by adam · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbox-community/netbox/pull/20592
Author: @jnovinger
Created: 10/15/2025
Status: Merged
Merged: 10/15/2025
Merged by: @jeremystretch

Base: mainHead: 20587-stale-contenttype-fix


📝 Commits (1)

  • c8171fa Fixes #20587: Handle stale ContentTypes in has_feature()

📊 Changes

1 file changed (+2 additions, -0 deletions)

View changed files

📝 netbox/netbox/models/features.py (+2 -0)

📄 Description

Fixes: #20587

Fixes #20587 (and its duplicate #20588) by adding a null check when handling stale ContentTypes in has_feature().

When running remove_stale_contenttypes (executed by upgrade.sh), the management command fails with TypeError: issubclass() arg 1 must be a class. This occurs when deleting ContentTypes that no longer have corresponding model classes—referred to as "stale" ContentTypes. These arise when models are renamed/removed between versions or when plugins are uninstalled.

The error path:

  1. Django's pre_delete signal fires when deleting the stale ContentType
  2. notify_object_changed() signal handler calls has_feature(instance, 'notifications')
  3. has_feature() calls model_class() on the ContentType, which returns None for stale types
  4. This None gets passed directly to the feature test lambda: issubclass(None, NotificationsMixin) → TypeError

Root Cause:

Commit 5ceb6a6 (which fixed #20290) changed the ContentType code path in has_feature() to use direct feature registry lookups in addition to ObjectType lookups. However, this refactoring inadvertently removed the null safety check that existed in the previous implementation.

https://gist.github.com/jnovinger/35948fc653c0425a5f9b207f9b77883f is available as a reproduction script to verify this fix.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbox-community/netbox/pull/20592 **Author:** [@jnovinger](https://github.com/jnovinger) **Created:** 10/15/2025 **Status:** ✅ Merged **Merged:** 10/15/2025 **Merged by:** [@jeremystretch](https://github.com/jeremystretch) **Base:** `main` ← **Head:** `20587-stale-contenttype-fix` --- ### 📝 Commits (1) - [`c8171fa`](https://github.com/netbox-community/netbox/commit/c8171fac568e741f59e48d586c28da2fe5523914) Fixes #20587: Handle stale ContentTypes in has_feature() ### 📊 Changes **1 file changed** (+2 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `netbox/netbox/models/features.py` (+2 -0) </details> ### 📄 Description ### Fixes: #20587 Fixes #20587 (and its duplicate #20588) by adding a null check when handling stale `ContentType`s in `has_feature()`. When running `remove_stale_contenttypes` (executed by `upgrade.sh`), the management command fails with `TypeError: issubclass() arg 1 must be a class`. This occurs when deleting ContentTypes that no longer have corresponding model classes—referred to as "stale" ContentTypes. These arise when models are renamed/removed between versions or when plugins are uninstalled. The error path: 1. Django's `pre_delete` signal fires when deleting the stale ContentType 2. `notify_object_changed()` signal handler calls `has_feature(instance, 'notifications')` 3. `has_feature()` calls `model_class()` on the ContentType, which returns `None` for stale types 4. This `None` gets passed directly to the feature test lambda: `issubclass(None, NotificationsMixin)` → TypeError Root Cause: Commit 5ceb6a6 (which fixed #20290) changed the ContentType code path in `has_feature()` to use direct feature registry lookups in addition to ObjectType lookups. However, this refactoring inadvertently removed the null safety check that existed in the previous implementation. https://gist.github.com/jnovinger/35948fc653c0425a5f9b207f9b77883f is available as a reproduction script to verify this fix. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
adam added the pull-request label 2025-12-30 00:25:07 +01:00
adam closed this issue 2025-12-30 00:25:07 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#15976