nautobot-app-ssot icon indicating copy to clipboard operation
nautobot-app-ssot copied to clipboard

Unable to open /plugins/ssot/history/ on one of my nautobot instance

Open dylanbob opened this issue 1 year ago • 6 comments

Environment

  • Python version: 3.11.9

  • Nautobot version: 2.2.4

  • nautobot-ssot version: How can I get that? probably 2.6.1

Expected Behavior

The /plugins/ssot/history/ would show

Observed Behavior

An error message was shown instead:

AttributeError at /plugins/ssot/history/

'NoneType' object has no attribute 'class_path'

Request Method: 	GET
Request URL: 	https://xxx.xxx.xxx.xxx/plugins/ssot/history/
Django Version: 	3.2.25
Exception Type: 	AttributeError
Exception Value: 	

'NoneType' object has no attribute 'class_path'

Exception Location: 	/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py, line 137, in get_source_url
Python Executable: 	/usr/local/bin/python3.11
Python Version: 	3.11.9
Python Path: 	

['.',
 '',
 '/opt/nautobot',
 '/usr/local/bin',
 '/usr/local/lib/python311.zip',
 '/usr/local/lib/python3.11',
 '/usr/local/lib/python3.11/lib-dynload',
 '/opt/nautobot/.local/lib/python3.11/site-packages',
 '/usr/local/lib/python3.11/site-packages']

Server time: 	Tue, 09 Jul 2024 16:10:41 +0200

Here is the complete traceback:

Environment:


Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/

Django Version: 3.2.25
Python Version: 3.11.9
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'corsheaders',
 'django_filters',
 'django_jinja',
 'django_tables2',
 'django_prometheus',
 'social_django',
 'taggit',
 'timezone_field',
 'nautobot.core.apps.NautobotConstanceConfig',
 'nautobot.core',
 'django.contrib.admin',
 'django_celery_beat',
 'django_celery_results',
 'rest_framework',
 'db_file_storage',
 'nautobot.circuits',
 'nautobot.dcim',
 'nautobot.ipam',
 'nautobot.extras',
 'nautobot.tenancy',
 'nautobot.users',
 'nautobot.virtualization',
 'drf_spectacular',
 'drf_spectacular_sidecar',
 'graphene_django',
 'health_check',
 'health_check.storage',
 'django_extensions',
 'constance.backends.database',
 'django_ajax_tables',
 'silk',
 'nautobot_device_lifecycle_mgmt.NautobotDeviceLifecycleManagementConfig',
 'nautobot_ssot.NautobotSSOTAppConfig',
 'nautobot_secrets_providers.NautobotSecretsProvidersConfig']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'silk.middleware.SilkyMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'nautobot.core.middleware.ExceptionHandlingMiddleware',
 'nautobot.core.middleware.RemoteUserMiddleware',
 'nautobot.core.middleware.ExternalAuthMiddleware',
 'nautobot.core.middleware.ObjectChangeMiddleware',
 'django_prometheus.middleware.PrometheusAfterMiddleware']


Template error:
In template /usr/local/lib/python3.11/site-packages/nautobot/core/templates/inc/table.html, error at line 20
   'NoneType' object has no attribute 'class_path'
   10 :                     {% else %}
   11 :                         <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
   12 :                     {% endif %}
   13 :                 {% endfor %}
   14 :             </tr>
   15 :         </thead>
   16 :     {% endif %}
   17 :     <tbody>
   18 :         {% for row in table.page.object_list|default:table.rows %}
   19 :             <tr {{ row.attrs.as_html }}>
   20 :                  {% for column, cell in row.items %} 
   21 :                     <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
   22 :                 {% endfor %}
   23 :             </tr>
   24 :         {% empty %}
   25 :             {% if table.empty_text %}
   26 :                 <tr>
   27 :                     <td colspan="{{ table.columns|length }}" class="text-center text-muted">&mdash; {{ table.empty_text }} &mdash;</td>
   28 :                 </tr>
   29 :             {% endif %}
   30 :         {% endfor %}


Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/mixins.py", line 166, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/generic.py", line 348, in get
    return render(request, self.template_name, context)
  File "/usr/local/lib/python3.11/site-packages/django/shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 519, in render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 315, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 195, in render
    return template.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 315, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/templatetags/django_tables2.py", line 166, in render
    return template.render(context={"table": table}, request=request)
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 214, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 170, in render
    values = list(values)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 244, in items
    column.current_value = self.get_cell(column.name)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 197, in get_cell
    return self._get_and_render_with(
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
    return render_func(bound_column, value)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 208, in _call_render
    return bound_column.link(content, **render_kwargs) if bound_column.link else content
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 153, in __call__
    attrs = self.get_attrs(**kwargs)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 148, in get_attrs
    attrs["href"] = self.compose_url(**kwargs)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 100, in compose_url
    return call_with_appropriate(self.url, kwargs)
  File "/usr/local/lib/python3.11/site-packages/django_tables2/utils.py", line 572, in call_with_appropriate
    return fn(**kwargs)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/tables.py", line 60, in <lambda>
    source = Column(linkify=lambda record: record.get_source_url())
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 137, in get_source_url
    kwargs={"class_path": self.job_result.job_model.class_path},

Exception Type: AttributeError at /plugins/ssot/history/
Exception Value: 'NoneType' object has no attribute 'class_path'

Steps to Reproduce

I do not realy know... I can only give you a lead, which is what I did.

  1. Import jobs using git
  2. Change/move jobs around, resyncing them
  3. Try to access /plugins/ssot/history/

dylanbob avatar Jul 09 '24 14:07 dylanbob

My interpretation here is that SSOT get_source_url() is not accounting for the possibility that there is a JobResult from a Job that has subsequently been uninstalled or deleted.

glennmatthews avatar Jul 09 '24 14:07 glennmatthews

Ran into this as well, seemed like exactly that. After I had deleted all my not installed apps after a git repo sync then this began to occur in the dashboard and the history. Though the history is giving a <class 'MemoryError'> and the Dashboard is giving me AttributeError: 'NoneType' object has no attribute 'class_path'

rifen avatar Jul 10 '24 15:07 rifen

Should be a straight-forward fix, to check if the job result exists here:

  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 137, in get_source_url
    kwargs={"class_path": self.job_result.job_model.class_path},

Kircheneer avatar Jul 23 '24 10:07 Kircheneer

@dylanbob

nautobot-ssot version: How can I get that? probably 2.6.1

Under Apps -> Installed Apps or with pip show

As for the actual issue, we have found that we are unable to replicate this, at least consistently. Are you able to do this?

Kircheneer avatar Sep 05 '24 07:09 Kircheneer

Hi. My environment changed since I opened this issue, now I have:

  • Python version: 3.11.9
  • Nautobot version: 2.3.1
  • nautobot-ssot version: 3.0.1

I was in 2.6.1 when I opened the issue.

I was able to reproduce the issue right now. Steps :

  1. import a job, using git (in my particular case)
  2. execute the job
  3. delete the job
  4. try to access /plugins/ssot/history/

At 4., the error occurs, here is the traceback:

Environment:


Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/

Django Version: 4.2.15
Python Version: 3.11.9
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'corsheaders',
 'django_filters',
 'django_jinja',
 'django_tables2',
 'django_prometheus',
 'social_django',
 'taggit',
 'timezone_field',
 'nautobot.core.apps.NautobotConstanceConfig',
 'nautobot.core',
 'django.contrib.admin',
 'django_celery_beat',
 'django_celery_results',
 'rest_framework',
 'db_file_storage',
 'nautobot.circuits',
 'nautobot.cloud',
 'nautobot.dcim',
 'nautobot.ipam',
 'nautobot.extras',
 'nautobot.tenancy',
 'nautobot.users',
 'nautobot.virtualization',
 'drf_spectacular',
 'drf_spectacular_sidecar',
 'graphene_django',
 'health_check',
 'health_check.storage',
 'django_extensions',
 'django_ajax_tables',
 'silk',
 'nautobot_ssot.NautobotSSOTAppConfig',
 'nautobot_secrets_providers.NautobotSecretsProvidersConfig']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'silk.middleware.SilkyMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'nautobot.core.middleware.ExceptionHandlingMiddleware',
 'nautobot.core.middleware.RemoteUserMiddleware',
 'nautobot.core.middleware.ExternalAuthMiddleware',
 'nautobot.core.middleware.ObjectChangeMiddleware',
 'django_prometheus.middleware.PrometheusAfterMiddleware']


Template error:
In template /usr/local/lib/python3.11/site-packages/nautobot/core/templates/inc/table.html, error at line 20
   'NoneType' object has no attribute 'class_path'
   10 :                     {% else %}
   11 :                         <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
   12 :                     {% endif %}
   13 :                 {% endfor %}
   14 :             </tr>
   15 :         </thead>
   16 :     {% endif %}
   17 :     <tbody>
   18 :         {% for row in table.page.object_list|default:table.rows %}
   19 :             <tr {{ row.attrs.as_html }}>
   20 :                  {% for column, cell in row.items %} 
   21 :                     <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
   22 :                 {% endfor %}
   23 :             </tr>
   24 :         {% empty %}
   25 :             {% if table.empty_text %}
   26 :                 <tr>
   27 :                     <td colspan="{{ table.columns|length }}" class="text-center text-muted">&mdash; {{ table.empty_text }} &mdash;</td>
   28 :                 </tr>
   29 :             {% endif %}
   30 :         {% endfor %}


Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/mixins.py", line 168, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/generic.py", line 391, in get
    return render(request, self.template_name, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/shortcuts.py", line 24, in render
    content = loader.render_to_string(template_name, context, request, using=using)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 175, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
    return compiled_parent._render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 63, in render
    result = block.nodelist.render(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 63, in render
    result = block.nodelist.render(context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 541, in render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 321, in render
    return nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 208, in render
    return template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 177, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 321, in render
    return nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/templatetags/django_tables2.py", line 166, in render
    return template.render(context={"table": table}, request=request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 175, in render
    return self._render(context)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
    return self.nodelist.render(context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
    return SafeString("".join([node.render_annotated(context) for node in self]))
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
    return SafeString("".join([node.render_annotated(context) for node in self]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 238, in render
    nodelist.append(node.render_annotated(context))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
    return self.render(context)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 193, in render
    values = list(values)
             ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 244, in items
    column.current_value = self.get_cell(column.name)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 197, in get_cell
    return self._get_and_render_with(
           
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
    return render_func(bound_column, value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 208, in _call_render
    return bound_column.link(content, **render_kwargs) if bound_column.link else content
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 153, in __call__
    attrs = self.get_attrs(**kwargs)
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 148, in get_attrs
    attrs["href"] = self.compose_url(**kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 100, in compose_url
    return call_with_appropriate(self.url, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_tables2/utils.py", line 572, in call_with_appropriate
    return fn(**kwargs)
           ^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/tables.py", line 58, in <lambda>
    source = Column(linkify=lambda record: record.get_source_url())
                                           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 138, in get_source_url
    kwargs={"class_path": self.job_result.job_model.class_path},
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: AttributeError at /plugins/ssot/history/
Exception Value: 'NoneType' object has no attribute 'class_path'

dylanbob avatar Sep 09 '24 15:09 dylanbob

@Kircheneer @dylanbob

I'm still unable to replicate this issue in my environment.

I have:

  • Nautobot v2.3.1
  • SSoT App v3.0.1
  • Python v3.11

Steps I took:

  • Imported SSoT jobs via Git repository
  • Ran job from Git repo a couple times
  • Deleted jobs by deleting get repo from Nautobot

When I go to /plugins/ssot/history/, I don't get any errors. image

I do get 404 errors when I try to open up one of the links to the missing job, though it's not the same error as described.

image

Renrut5 avatar Sep 26 '24 14:09 Renrut5

Reviewing this and the error from @dylanbob I believe this is an issue with your Job being installed correctly. The NoneType in question is the job_model so you need to fix that.

jdrew82 avatar Nov 14 '25 15:11 jdrew82