> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/curator/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/curator/_mcp/server.

# nemo_curator.tasks.sentinels

Payload-less marker tasks.

`EmptyTask` seeds a pipeline (the implicit root id `"0"`). The resumability
layer adds two more markers on the same :class:`SentinelTask` base:

* `NoneTask` — this slot was intentionally filtered. The resumability counter
  treats it as a consumed branch (decrements). The adapter auto-wraps a
  returned `None` as a `NoneTask`.
* `FailedTask` — this slot failed and should be retried on resume. The counter
  is NOT decremented, so its source stays pending and reruns.

All carry no payload (`data is None`) and get their `task_id` assigned by
the executor adapter; sentinels are stripped before the next stage. Construct
with `EmptyTask()` / `NoneTask()` / `FailedTask()`.

## Module Contents

### Classes

| Name                                                         | Description                                                                |
| ------------------------------------------------------------ | -------------------------------------------------------------------------- |
| [`EmptyTask`](#nemo_curator-tasks-sentinels-EmptyTask)       | Seeds a pipeline with `task_id="0"` — the implicit root every task         |
| [`FailedTask`](#nemo_curator-tasks-sentinels-FailedTask)     | Marks a slot as failed → retried on resume (counter does NOT decrement).   |
| [`NoneTask`](#nemo_curator-tasks-sentinels-NoneTask)         | Marks a slot as intentionally filtered (resumability counter decrements).  |
| [`SentinelTask`](#nemo_curator-tasks-sentinels-SentinelTask) | Base for payload-less marker tasks: no data, framework-assigned `task_id`. |

### API

```python
class nemo_curator.tasks.sentinels.EmptyTask(
    dataset_name: str = 'empty',
    data: None = None,
    _stage_perf: list[nemo_curator.utils.performance_utils.StagePerfStats] = list(),
    _metadata: dict[str, typing.Any] = dict()
)
```

Dataclass

**Bases:** [SentinelTask](#nemo_curator-tasks-sentinels-SentinelTask)

Seeds a pipeline with `task_id="0"` — the implicit root every task
descends from (so all ids share the `"0"` prefix).

**`dataset_name`** `str = 'empty'`

---

**`task_id`** `str = field(init=False, default='0')`

---

```python
class nemo_curator.tasks.sentinels.FailedTask(
    dataset_name: str = 'failed',
    data: None = None,
    _stage_perf: list[nemo_curator.utils.performance_utils.StagePerfStats] = list(),
    _metadata: dict[str, typing.Any] = dict()
)
```

Dataclass

**Bases:** [SentinelTask](#nemo_curator-tasks-sentinels-SentinelTask)

Marks a slot as failed → retried on resume (counter does NOT decrement).

**`dataset_name`** `str = 'failed'`

---

```python
class nemo_curator.tasks.sentinels.NoneTask(
    dataset_name: str = 'none',
    data: None = None,
    _stage_perf: list[nemo_curator.utils.performance_utils.StagePerfStats] = list(),
    _metadata: dict[str, typing.Any] = dict()
)
```

Dataclass

**Bases:** [SentinelTask](#nemo_curator-tasks-sentinels-SentinelTask)

Marks a slot as intentionally filtered (resumability counter decrements).

**`dataset_name`** `str = 'none'`

---

```python
class nemo_curator.tasks.sentinels.SentinelTask(
    dataset_name: str,
    data: None = None,
    _stage_perf: list[nemo_curator.utils.performance_utils.StagePerfStats] = list(),
    _metadata: dict[str, typing.Any] = dict()
)
```

Dataclass

**Bases:** [Task\[None\]](/nemo-curator/nemo_curator/tasks/tasks#nemo_curator-tasks-tasks-Task)

Base for payload-less marker tasks: no data, framework-assigned `task_id`.

**`data`** `None = None`

---

**`num_items`** `int`

---

```python
nemo_curator.tasks.sentinels.SentinelTask.__post_init__() -> None
```

```python
nemo_curator.tasks.sentinels.SentinelTask.validate() -> bool
```