Skip to content

Job Structure

Introduction

Jobs in Nautobot are Python classes designed to perform automated tasks within the Nautobot environment. Each Job can consist of:

  • Metadata attributes — control how the Job appears and behaves in the UI (e.g. name, permissions, scheduling rules)
  • Input variables — define the user-supplied inputs for the Job
  • Special methods — control the execution flow (run(), on_success(), etc.)
  • Registration logic — every Job must be explicitly registered with register_jobs() to be discoverable

It's essential to distinguish between metadata attributes and input variables clearly:

  • Metadata Attributes define how the Job itself behaves within the Nautobot platform (such as display name, permissions, execution constraints).
  • Input Variables define user-supplied inputs that can influence the Job's execution logic.

Below, each section details how to implement these components in your Jobs effectively.

Job Class vs. Job Record

Nautobot separates the Job class (your Python code) from the Job record (a database entry that stores metadata).

Job Class Job Record
Python code in a module Created automatically by Nautobot
Inherits from Job Stored in the database
Defines metadata, variables, logic Stores enabled state, name override, queue config
Discovered on startup Updated by post_upgrade or Git resync

The Job record must exist for the Job to run — but Nautobot always executes the logic from your source code. This separation allows changes to the Job source without modifying the database.

Job Registration

All Job classes must be registered with Nautobot at import time to be discoverable and runnable.

This is done using the register_jobs() helper:

from nautobot.apps.jobs import Job, register_jobs

class HelloWorldJob(Job):
    ...

register_jobs(HelloWorldJob)

You can register multiple jobs at once:

register_jobs(CleanupDevices, SyncInventory)

Where to Register

  • For files in JOBS_ROOT, register Jobs directly in the file or from a top-level __init__.py that imports submodules.
  • For Git-based Jobs, use the jobs/__init__.py file in the repo to register all your Job classes.
  • For App-based Jobs, register them in the module defined by your App's NautobotAppConfig.jobs property (default: jobs).

If you don't call register_jobs(), Nautobot will skip your class during startup, even if it's defined correctly.

Unregistered Jobs are invisible

If you forget to call register_jobs(), Nautobot won't discover your Job — it won't appear in the UI, API, or be runnable at all.

Module Metadata Attributes

name (Grouping)

You can define a global constant called name within a job module (the Python file which contains one or more Job classes) to set the default grouping under which the Jobs in this module will be displayed in the Nautobot UI. If this value is not defined, the module's file name will be used. This "grouping" value may also be defined or overridden when editing Job records in the database.

Note

In some UI elements and API endpoints, the module file name is displayed in addition to or in place of this attribute, so even if defining this attribute, you should still choose an appropriately explanatory file name as well.

Class Metadata Attributes

Job-specific attributes may be defined under a class named Meta within each Job class you implement. All of these are optional but encouraged for clearer user experience and administration.

name

This is the human-friendly name of your Job, as displayed in the Nautobot UI. If not set, the class name will be used.

Note

In some UI elements and API endpoints, the class name is displayed in addition to or in place of this attribute, so even if defining this attribute, you should still choose an appropriately explanatory class name as well.

description

An optional human-friendly description of what this Job does. This can accept either plain text, Markdown-formatted text, or a limited subset of HTML. It can also be multiple lines:

class ExampleJob(Job):
    class Meta:
        description = """
            This job does a number of interesting things.

             1. It hacks the Gibson
             2. It immanentizes the eschaton
             3. It's a floor wax *and* a dessert topping
        """

If you code a multi-line description, the first line only will be used in the description column of the Jobs list, while the full description will be rendered in the Job detail view, submission, approval, and results pages.

approval_required

Default: False

A boolean that will mark this Job as requiring approval from another user to be run. For more details on approvals, please refer to the section on scheduling and approvals.

dryrun_default

Changed in version 2.0.0 — Replacement for commit_default

The commit_default field was renamed to dryrun_default and the default value was changed from True to False. The commit functionality that provided an automatic rollback of database changes if the Job failed was removed.

Default: False

If the Job implements a DryRunVar, what its default value should be. The checkbox to enable dryrun when executing a Job is unchecked by default in the Nautobot UI. You can set dryrun_default to True under the Meta class if you want this option to instead be checked by default.

class MyJob(Job):
    class Meta:
        dryrun_default = True

field_order

Default: []

A list of strings (field names) representing the order your Job variables should be rendered as form fields in the Job submission UI. If not defined, the variables will be listed in order of their definition in the code. If variables are defined on a parent class and no field order is defined, the parent class variables will appear before the subclass variables.

has_sensitive_variables

Default: True

Unless set to False, it prevents the Job's input parameters from being saved to the database. This defaults to True so as to protect against inadvertent database exposure of input parameters that may include sensitive data such as passwords or other user credentials. Review whether each Job's inputs contain any such variables before setting this to False; if a Job does contain sensitive inputs, if possible you should consider whether the Job could be re-implemented using Nautobot's Secrets feature as a way to ensure that the sensitive data is not directly provided as a Job variable at all.

Important notes about Jobs with sensitive variables:

  • Such Jobs cannot be scheduled to run in the future or on a recurring schedule (as Scheduled Jobs must by necessity store their variables in the database for future reference).
  • Jobs with sensitive variables cannot be marked as requiring approval (as Jobs pending approval must store their variables in the database until approved).

hidden

Default: False

A Boolean that if set to True prevents the Job from being displayed by default in the list of Jobs in the Nautobot UI.

Since the Job execution framework is designed to be generic, there may be several technical Jobs defined by users which interact with or are invoked by external systems. In such cases, these Jobs are not meant to be executed by a human and likely do not make sense to expose to end users for execution, and thus having them exposed in the UI at all is extraneous.

Important notes about hidden Jobs:

  • This is merely hiding them by default from the web interface. It is NOT a security feature.
  • In the Jobs list view it is possible to filter to "Hidden: (no selection)" or even "Hidden: Yes" to list the hidden Jobs.
  • All Job UI and REST API endpoints still exist for hidden Jobs and can be accessed by any user who is aware of their existence.
  • Hidden Jobs can still be executed through the UI or the REST API given the appropriate URL.
  • Results for hidden Jobs will still appear in the Job Results list after they are run.

is_singleton

Added in version 2.4.0

Default: False A Boolean that if set to True prevents the job from running twice simultaneously.

Any duplicate job instances will error out with a singleton-specific error message.

Important notes about singleton jobs:

  • The singleton functionality is implemented with a Redis key set to timeout either on the hard time out of the job or whenever the job terminates.
    • Therefore, a restart of Redis will wipe the singleton locks
  • A checkbox on the job run form makes it possible to force the singleton lock to be overridden. This makes it possible to recover from failure scenarios such as the original singleton job being stopped before it can unset the lock.

read_only

Changed in version 2.0.0 — No automatic functionality

The read_only flag no longer changes the behavior of Nautobot core and is up to the Job author to decide whether their Job should be considered read only.

Default: False

A boolean that can be set by the Job author to indicate that the Job does not make any changes to the environment. What behavior makes each Job "read only" is up to the individual Job author to decide. Note that user input may still be optionally collected with read-only Jobs via Job variables, as described below.

soft_time_limit

An int or float value, in seconds, which can be used to override the default soft time limit for a Job task to complete.

The celery.exceptions.SoftTimeLimitExceeded exception will be raised when this soft time limit is exceeded. The Job task can catch this to clean up before the hard time limit (10 minutes by default) is reached:

from celery.exceptions import SoftTimeLimitExceeded
from nautobot.apps.jobs import Job

class ExampleJobWithSoftTimeLimit(Job):
    class Meta:
        name = "Soft Time Limit"
        description = "Set a soft time limit of 10 seconds"
        soft_time_limit = 10

    def run(self):
        try:
            # code which might take longer than 10 seconds to run
            job_code()
        except SoftTimeLimitExceeded:
            # any clean up code
            cleanup_in_a_hurry()

task_queues

Default: []

A list of Job Queue names that the Job can be routed to. An empty list will default to only allowing the user to select the default Celery queue (default unless changed by an administrator). The queue specified in the Job's default_job_queue will be used if a queue is not specified in a Job run API call.

Changed in version 2.4.0 — Changed default queue selection

As a result of the addition of Job Queues, the default queue when running a Job without explicitly selecting a queue is now the job queue specified in the default_job_queue field on the Job model. default_job_queue fields for any existing Job instances are automatically populated with the name of the first entry in task_queues list of the Job class. When task_queues list on the Job class is empty, the corresponding Job instance's default_job_queue will be the job queue with the name provided by settings.CELERY_TASK_DEFAULT_QUEUE. You can also override the initial default_job_queue by setting default_job_queue_override to True and assign the field with a different Job Queue instance.

Note

A worker must be listening on the requested queue or the Job will not run. See the documentation on task queues for more information.

template_name

A Django template path which provides additional code to customize the Job's submission form. This template should extend the existing Job template, extras/job.html, otherwise the base form and functionality may not be available.

Note

Because the template must be discoverable by Django's template engine, it typically must be provided by Nautobot itself or a Nautobot App. There's no standard mechanism for Jobs in JOBS_ROOT or Git repositories to supply such templates.

A template can provide additional JavaScript, CSS, or even display HTML. A good starting template would be:

{% extends 'extras/job.html' %}

{% block extra_styles %}
    {{ block.super }}
    <!-- Add additional CSS here. -->
{% endblock %}
{% block content %}
    {{ block.super }}
    <!-- Add additional HTML here. -->
{% endblock content %}
{% block javascript %}
    {{ block.super }}
    <!-- Add additional JavaScript here. -->
{% endblock javascript %}
Added in version 2.2.0 — Additional blocks

Added the job_form and schedule_form sub-blocks to extras/job.html, for use by Jobs that just want to override the rendered forms without replacing all of {% block content %}.

For another example checkout the template used in the Example App in the GitHub repo.

time_limit

An int or float value, in seconds, which can be used to override the default hard time limit (10 minutes by default) for a Job task to complete.

Unlike the soft_time_limit above, no exceptions are raised when a time_limit is exceeded. The task will just terminate silently:

from nautobot.apps.jobs import Job

class ExampleJobWithHardTimeLimit(Job):
    class Meta:
        name = "Hard Time Limit"
        description = "Set a hard time limit of 10 seconds`"
        time_limit = 10

    def run(self):
        # code which might take longer than 10 seconds to run
        # this code will fail silently if the time_limit is exceeded
        job_code()

time_limit versus soft_time_limit

If the time_limit is set to a value less than or equal to the soft_time_limit, a warning log is generated to inform the user that this Job will fail silently after the time_limit as the soft_time_limit will never be reached.

Variables

Variables allow your Job to accept user input via the Nautobot UI, but they are optional; if your Job does not require any user input, there is no need to define any variables. Conversely, if you are making use of user input in your Job, you must also implement the run() method, as it is the only entry point to your Job that has visibility into the variable values provided by the user.

This example defines two input variables using StringVar and IntegerVar, which are passed as keyword arguments into the run() method. The values provided by the user at runtime are then used inside a loop to print a customized greeting message using self.logger.info(). By logging each message, the Job provides immediate feedback in the JobResult view. Finally, the class is registered using register_jobs() to ensure it can be discovered and run within Nautobot.

from nautobot.apps import jobs

name = "Hello Jobs"

class HelloJobs(jobs.Job):
    class Meta:
        name = "Say Hello"

    person_name = jobs.StringVar(
        description="Name of the person to greet",
        default="world"
    )

    greeting_count = jobs.IntegerVar(
        description="How many times to greet",
        default=1,
        min_value=1
    )

    def run(self, *, person_name, greeting_count):
        for i in range(greeting_count):
            self.logger.info("Hello, %s! (%d)", person_name, i + 1)

jobs.register_jobs(HelloJobs)

The remainder of this section documents the various supported variable types and how to make use of them.

Default Variable Options

All Job variables support the following default options:

  • default - The field's default value
  • description - A brief user-friendly description of the field
  • label - The field name to be displayed in the rendered form
  • required - Indicates whether the field is mandatory (all fields are required by default)
  • widget - The class of form widget to use (see the Django documentation)

StringVar

Stores a string of characters (i.e. text). Options include:

  • min_length - Minimum number of characters
  • max_length - Maximum number of characters
  • regex - A regular expression against which the provided value must match

Note that min_length and max_length can be set to the same number to effect a fixed-length field.

TextVar

Arbitrary text of any length. Renders as a multi-line text input field.

JSONVar

Added in version 2.1.0

Accepts JSON-formatted data of any length. Renders as a multi-line text input field. The variable passed to run() method on the Job has been serialized to the appropriate Python objects.

from nautobot.apps.jobs import Job, JSONVar

class ExampleJSONVarJob(Job):
    var1 = JSONVar(
        description="Provide a JSON object with a 'key1' field.",
    )

    def run(self, var1):
        # Example input: {"key1": "value1"}
        if "key1" in var1:
            self.logger.info("The value of key1 is: %s", var1["key1"])
        else:
            self.logger.error("Missing required key: key1")

This Job uses a JSONVar to accept a structured input from the user. For example, the user might submit {"key1": "value1"}. Nautobot first validates that the input is valid JSON, then automatically deserializes it into a Python dictionary. Inside the Job, you can access the dictionary directly - in this case, logging the value of key1 or raising an error if it's missing. This is a simple way to demonstrate structured input, useful for things like configuration blobs or external API payloads, without needing to manually parse the JSON yourself.

IntegerVar

Stores a numeric integer. Options include:

  • min_value - Minimum value
  • max_value - Maximum value

BooleanVar

A true/false flag. This field has no options beyond the defaults listed above.

DryRunVar

A true/false flag with special handling for Jobs that require approval. If dryrun = DryRunVar() is declared on a Job class, approval may be bypassed if dryrun is set to True on Job execution.

ChoiceVar

A set of choices from which the user can select one.

  • choices - A list of (value, label) tuples representing the available choices. For example:
from nautobot.apps.jobs import Job, ChoiceVar, register_jobs

DIRECTIONS = (
    ("n", "North"),
    ("s", "South"),
    ("e", "East"),
    ("w", "West"),
)

class CompassJob(Job):
    direction = ChoiceVar(
        choices=DIRECTIONS,
        description="Choose a cardinal direction."
    )

    def run(self, *, direction):
        self.logger.info("You chose to go: %s", dict(DIRECTIONS)[direction])

register_jobs(CompassJob)

This example uses a ChoiceVar to let the user select one option from a list of predefined values. When the Job runs, the selected value (e.g., "n") is passed to the run() method. The Job then looks up the human-readable label ("North") and logs it. This pattern is useful when you want to limit input to a safe, predictable set of options.

MultiChoiceVar

Similar to ChoiceVar, but allows for the selection of multiple choices.

ObjectVar

A ObjectVar allows users to select a single Nautobot object (such as a device, interface, or location) via the UI or API. It accepts several options to customize its behavior, from simple selections to dynamic filters and nested fields.

You can customize how objects appear in the selection dropdown and what subset of records are made available using the following arguments:

  • model: The Django model class to query (e.g., Device, Location, IPAddress).
  • display_field: The model attribute to display for each object in the UI dropdown. Defaults to the object's display property. You can specify any valid attribute, including nested fields (e.g., vlan_group.name) or computed fields (e.g., computed_fields.mycustomfield).
  • query_params: A dictionary of query parameters used to filter the available options. These follow the same structure as the Nautobot REST API.
  • null_option: An optional label that represents an empty selection.

Basic Usage

from nautobot.apps.jobs import Job, ObjectVar, register_jobs
from nautobot.dcim.models import Device

class ChooseDevice(Job):
    device = ObjectVar(
        model=Device,
        description="Pick a device to validate."
    )

    def run(self, *, device):
        self.logger.info("You selected the device: %s", device)

register_jobs(ChooseDevice)

This Job lets a user select a Device object from a dropdown. That selected object is passed as an argument to the run() method. This pattern is useful for Jobs that operate on a specific record from Nautobot.

Customizing Display Field

By default, Nautobot will show each object's display field in the dropdown. To show a different field-such as a hostname, IP, or a related model's attribute - you can override it using display_field.

device_ip = ObjectVar(
    model=IPAddress,
    display_field="dns_name",  # Instead of the default "address" or "display"
)

You can also use dot notation to reference nested or related fields, such as a VLAN's group name:

vlan = ObjectVar(
    model=VLAN,
    display_field="vlan_group.name",
    query_params={"depth": 1}  # Ensures nested objects are populated
)

In the example above, "depth": 1 was needed to influence REST API to include details of the associated records.

Using Computed Fields

Another example of using the nested reference would be to access computed fields of the model. Nautobot supports selecting computed fields as part of the display_field, provided the API query includes them:

interface = ObjectVar(
    model=Interface,
    display_field="computed_fields.mycustomfield",
    query_params={"include": "computed_fields"}
)

This allows users to see custom-calculated values - like interface capacity scores or normalized labels - in the dropdown UI. It's especially useful when default display fields aren't meaningful enough on their own for selection.

To limit the selections available within the list, additional query parameters can be passed as the query_params dictionary. For example, to show only devices with an "active" status:

device = ObjectVar(
    model=Device,
    query_params={
        'status': 'active'
    }
)

Filtering Options with query_params

Use query_params to filter which objects appear in the dropdown. For example, only show devices that are "active":

device = ObjectVar(
    model=Device,
    query_params={"status": "active"}
)

Multiple values can be specified by assigning a list to the dictionary key. It is also possible to reference the value of other fields in the form by prepending a dollar sign ($) to the variable's name. The keys you can use in this dictionary are the same ones that are available in the REST API - as an example it is also possible to filter the Location ObjectVar for its location_type and tenant_group.

location_type = ObjectVar(
    model=LocationType
)
tenant_group = ObjectVar(
    model=TenantGroup
)
location = ObjectVar(
    model=Location,
    query_params={
        "location_type": "$location_type",
        "tenant_group": "$tenant_group"
    }
)

MultiObjectVar

Similar to ObjectVar, but allows for the selection of multiple objects.

FileVar

An uploaded file provided via FileVar is passed to the Job's run() method as an in-memory file - like object, typically an InMemoryUploadedFile. These are temporary and exist only for the duration of the Job execution — they are not saved automatically.

The example below shows how to use FileVar to upload a CSV file, decode its contents, and process each row with Python's csv.DictReader. This pattern is useful when working with structured input formats such as device inventories, IP assignments, or user data.

If you want to retain output from a Job (e.g. processed data or error logs), you can use self.create_file() to save and expose results via the JobResult detail page.

import csv
from nautobot.apps.jobs import Job, FileVar, register_jobs

class ReadCSVJob(Job):
    class Meta:
        name = "Read CSV Upload"

    input_file = FileVar(description="Upload a CSV file with hostname,ip_address columns")

    def run(self, *, input_file):
        decoded_file = input_file.read().decode("utf-8").splitlines()
        reader = csv.DictReader(decoded_file)
        for row in reader:
            self.logger.info("Hostname: %s, IP Address: %s", row["hostname"], row["ip_address"])

register_jobs(ReadCSVJob)

Note

Files provided via FileVar must be read and processed during the run() method. If needed, use self.create_file() to persist any output for download after execution.

IPAddressVar

An IPv4 or IPv6 address, without a mask. Returns a netaddr.IPAddress object.

IPAddressWithMaskVar

An IPv4 or IPv6 address with a mask. Returns a netaddr.IPNetwork object which includes the mask.

IPNetworkVar

An IPv4 or IPv6 network with a mask. Returns a netaddr.IPNetwork object. Two attributes are available to validate the provided mask:

  • min_prefix_length - Minimum length of the mask
  • max_prefix_length - Maximum length of the mask

Special Methods

Special methods allow you to manage the execution lifecycle of a Job, providing hooks to run code at critical points such as initialization, successful execution, or error handling. Implementing these methods can improve robustness, debugging, and reliability of Jobs.

Nautobot Jobs when executed will be instantiated by Nautobot, then Nautobot will call in order the special API methods before_start(), run(), on_success()/on_failure(), and after_return(). You must implement the run() method; the other methods have default implementations that do nothing.

As Jobs are Python classes, you are of course free to define any number of other helper methods or functions that you call yourself from within any of the above special methods, but the above are the only ones that will be automatically called.

Removed in version 2.0.0 — Removal of test and post_run special methods

The NetBox backwards compatible test_*() and post_run() special methods have been removed.

The before_start() Method

The before_start() method may optionally be implemented to perform any appropriate Job-specific setup before the run() method is called. It has the signature before_start(self, task_id, args, kwargs) for historical reasons; the task_id parameter will always be identical to self.request.id, the args parameter will generally be empty, and any user-specified variables passed into the Job execution will be present in the kwargs parameter.

The return value from before_start() is ignored, but if it raises any exception, the Job result status will be marked as FAILURE and run() will not be called.

The create_file() Method

Added in version 2.1.0

Jobs can generate output files during execution using the create_file() method. These files are saved and made available to the user from the JobResult detail view's Advanced tab or via the REST API.

This is useful when you want to:

  • Generate downloadable reports
  • Return structured outputs (e.g. CSV, JSON)
  • Provide a summary or log of what the Job did
from nautobot.apps.jobs import Job, register_jobs

class ExportText(Job):
    class Meta:
        name = "Export Text File"

    def run(self):
        self.create_file("output.txt", "Export completed successfully.")
        self.logger.info("File has been created for download.")

register_jobs(ExportText)

The create_file() method accepts a filename and file contents (as str or bytes). Files are saved alongside the JobResult and remain available until the JobResult is deleted.

Note

The maximum file size and storage backend for output files are controlled by the JOB_CREATE_FILE_MAX_SIZE and JOB_FILE_IO_STORAGE settings.

The run() Method

The run() method is the core of every Job and is required. It receives user-supplied inputs (defined as variables on the class) as keyword arguments. Inside this method, you define the logic that the Job will execute-such as querying data, applying changes, or interacting with external systems. The method can return a value, which will be saved in the JobResult and displayed in the UI and API.

Here's a basic structure:

from nautobot.apps.jobs import Job, StringVar

class SimpleGreetingJob(Job):
    name_input = StringVar(description="Who should we greet?")

    def run(self, *, name_input):
        self.logger.info("Hello, %s!", name_input)

register_jobs(SimpleGreetingJob)

Again, defining user variables is totally optional; you may create a Job with a run() method with only the self argument if no user input is needed.

Use validated_save() where applicable

When writing Jobs that create and manipulate data it is recommended to make use of the validated_save() convenience method which exists on all core models. This method saves the instance data but first enforces model validation logic. Simply calling save() on the model instance does not enforce validation automatically and may lead to bad data. See the development best practices.

Be cautious around bulk operations

The Django ORM provides methods to create/edit many objects at once, namely bulk_create() and update(). These are best avoided in most cases as they bypass a model's built-in validation and can easily lead to database corruption if not used carefully.

Returning and Failing from run()

The return value of the run() method is saved to the JobResult and is viewable in both the Nautobot UI and API. If run() completes without error, the Job is automatically marked as SUCCESS.

There are two ways to explicitly mark a Job as failed:

  • Call self.fail("message") to mark the Job as FAILURE without raising an exception or halting execution.
  • Raise an exception to stop the Job immediately. Nautobot will capture the error and traceback in the JobResult.

Calling self.fail() is useful for validation or soft failures that don't require a hard stop.

from nautobot.apps.jobs import Job, StringVar, register_jobs

class CheckOccasion(Job):
    occasion = StringVar(description="Enter an occasion")

    def run(self, *, occasion):
        if not occasion.startswith("Taco"):
            self.logger.error("Occasion must begin with 'Taco'")
            raise Exception("Input validation failed.")

        if not occasion.endswith("Tuesday"):
            self.fail("It's supposed to be Tuesday!")  # Marks job as FAILURE without traceback

        self.logger.info("Perfect! Today is %s", occasion)
        return occasion

register_jobs(CheckOccasion)

In this example, if the occasion input doesn't start with "Taco", an exception is raised and the Job fails immediately. If the input ends incorrectly (but started correctly), the Job continues but is still marked as failed using self.fail(). Otherwise, the Job logs a success message and completes normally, returning the value to the JobResult.

The on_success() Method

If both before_start() and run() are successful, the on_success() method will be called next, if implemented. It has the signature on_success(self, retval, task_id, args, kwargs); as with before_start() the task_id and args parameters can generally be ignored, while retval is the return value from run(), and kwargs will contain the user-specified variables passed into the Job execution.

The on_failure() Method

If either before_start() or run() raises any unhandled exception, or reports a failure overall through fail(), the on_failure() method will be called next, if implemented. It has the signature on_failure(self, exc, task_id, args, kwargs, einfo); of these parameters, the exc will contain the exception that was raised (if any) or the return value from before_start() or run() (otherwise), and kwargs will contain the user-specified variables passed into the Job.

The after_return() Method

Regardless of the overall Job execution success or failure, the after_return() method will be called after on_success() or on_failure(). It has the signature after_return(self, status, retval, task_id, args, kwargs, einfo); the status will indicate success or failure (using the JobResultStatusChoices enum), retval is either the return value from run() or the exception raised, and once again kwargs contains the user variables.

Reserved Names: Avoiding Collisions with Job Internals

When writing Jobs, it's important to avoid reusing internal attribute or method names from the Job class. Doing so can interfere with how Jobs are registered, rendered, or executed. The following table outlines reserved names you should not use for variable names or method overrides.

There are many attributes and methods of the Job class that serve as reserved names. You must be careful when implementing custom methods or defining the user input variables for your Job that you do not inadvertently "step on" one of these reserved attributes causing unexpected behavior or errors.

Don't override built-in attributes

A common mistake is redefining the reserved name attribute as a user input variable. This overrides the Job's display name and may prevent the Job from running correctly.

As of Nautobot 2.4.0, the current list of reserved names (not including low-level Python built-ins such as __dict__ or __str__ includes:

Reserved Name Purpose
after_return special method
approval_required metadata property
as_form class method
as_form_class class method
before_start special method
celery_kwargs property
class_path class property
class_path_dotted deprecated class property
class_path_js_escaped class property
create_file helper method
description metadata property
description_first_line metadata property
deserialize_data internal class method
dryrun_default metadata property
fail helper method
field_order metadata property
file_path deprecated class property
grouping module metadata property
has_sensitive_variables metadata property
hidden metadata property
is_singleton metadata property
job_model property
job_result property
load_json helper method
load_yaml helper method
name metadata property
on_failure special method
on_retry reserved as a future special method (not present)
on_success special method
prepare_job_kwargs internal class method
properties_dict class property
read_only metadata property
registered_name deprecated class property
run special method
serialize_data internal method
soft_time_limit metadata property
supports_dryrun class property
task_queues metadata property
template_name metadata property
time_limit metadata property
user property
validate_data internal class method