---
id: "custom-node"
type: "rule"
severity: "warning"
url: "https://localhost:3000/catalogue/rules/custom-node"
---

# Custom node

A node uses the custom kind, so the catalogue does not describe it and no rule can check anything about it.

| | |
|---|---|
| Severity | warning |
| Selects | every node of kind custom |
| Components in scope | 1 |

## Why

A custom node is a hole in the model: the catalogue has no word for it, so no rule can check anything about it. It is meant to be temporary, and naming it in the catalogue closes the hole.

## What it checks

It looks at every node of kind custom, and fires when:

- the node's `anyProperty` has no value

Message template:

```
Node '{{node.id}}' is custom: no rule can judge it. Replace it with a catalogue component or contribute one (docs/governance.md).
```

## Applies to

- [Custom](https://localhost:3000/catalogue/kinds/custom.md) `custom`

1 catalogue components fall under it.

## Tripped by

Reference designs whose broken twin names this rule in its header:

- [custom-escape-hatch](https://localhost:3000/d/zeema/custom-escape-hatch)

## Source (`rule` YAML, verbatim)

```yaml
# yaml-language-server: $schema=../schema/rule.schema.json
# A custom node is a hole in the model: the catalogue does not name it, so nothing can be
# checked about it. Fires on every custom node, unconditionally. Tripped by
# designs/reference/custom-escape-hatch/design.broken.yaml.
schemaVersion: "1"
type: "rule"
id: "custom-node"
severity: "warning"
select:
  node:
    kind: "custom"
# `when` is required and the custom kind defines no properties, so nothing ever resolves on
# one of these nodes: this predicate is how the fixed predicate set spells "always".
when:
  prop: "anyProperty"
  exists: false
message: "Node '{{node.id}}' is custom: no rule can judge it. Replace it with a catalogue component or contribute one (docs/governance.md)."
```

Human page: https://localhost:3000/catalogue/rules/custom-node
