-
Notifications
You must be signed in to change notification settings - Fork 159
docs: add subgraph linter guide #1065
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
idalithb
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please review suggested changes, but I've approved 😄
|
|
||
| [Subgraph Linter](https://github.com/graphops/subgraph-linter) is a static analysis tool for The Graph subgraphs. It analyzes your subgraph code before deployment and surfaces common patterns that lead to runtime crashes, corrupted entity state, silent data errors, or unnecessary performance overhead. | ||
|
|
||
| Instead of discovering issues after deploying and indexing (or worse, after production failures), Subgraph Linter complements existing tooling to help you catch problems locally while you write code. It does not replace testing (either runtime or via unit tests), but it can dramatically reduce the class of bugs that ever make it to production deployments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Instead of discovering issues after deploying and indexing (or worse, after production failures), Subgraph Linter complements existing tooling to help you catch problems locally while you write code. It does not replace testing (either runtime or via unit tests), but it can dramatically reduce the class of bugs that ever make it to production deployments. | |
| It complements existing tools by helping you catch problems locally while writing code, rather than discovering them after deployment or in production. It does not replace testing (runtime or unit tests), but it can reduce the number of bugs that make it to production. |
|
|
||
| Instead of discovering issues after deploying and indexing (or worse, after production failures), Subgraph Linter complements existing tooling to help you catch problems locally while you write code. It does not replace testing (either runtime or via unit tests), but it can dramatically reduce the class of bugs that ever make it to production deployments. | ||
|
|
||
| ## Why run Subgraph Linter? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ## Why run Subgraph Linter? | |
| ## When to use it |
|
|
||
| ## Why run Subgraph Linter? | ||
|
|
||
| Subgraph handlers often fail in subtle ways that don’t show up until indexing starts: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Subgraph handlers often fail in subtle ways that don’t show up until indexing starts: | |
| Run Subgraph Linter when you want to detect handler and mapping issues that don't often appear until indexing starts, such as: |
| - Entities are saved with missing required fields | ||
| - Multiple instances of the same entity handled at the same time causing overwrite issues | ||
| - Optional values are force-unwrapped without checks | ||
| - Divisions happen without proving the divisor is non-zero | ||
| - Derived fields are mutated directly or left stale | ||
| - Contract calls are made without being declared in the manifest | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| - Entities are saved with missing required fields | |
| - Multiple instances of the same entity handled at the same time causing overwrite issues | |
| - Optional values are force-unwrapped without checks | |
| - Divisions happen without proving the divisor is non-zero | |
| - Derived fields are mutated directly or left stale | |
| - Contract calls are made without being declared in the manifest | |
| - Entities saved with missing required fields | |
| - Entity overwrite issues from concurrent/stale instances | |
| - Optional values force-unwrapped without checks | |
| - Divisions without guaranteeing a non-zero denominator | |
| - `@derivedFrom` fields mutated directly or left stale | |
| - Contract calls are used without being declared in the manifest |
| ## How it works | ||
|
|
||
| Subgraph Linter analyzes your subgraph manifest and the mapping files referenced by it. It understands how Graph mappings are typically structured and tracks things such as: | ||
|
|
||
| - Entity identity (type + id) | ||
| - Loads, saves, and reloads | ||
| - Helper call graphs (including nested helpers) | ||
| - Assignments and mutations | ||
| - Control flow guards (null checks, zero checks, short-circuit logic) | ||
|
|
||
| From this, it applies a set of targeted checks designed specifically for problematic subgraph code patterns. | ||
|
|
||
| ## Key checks | ||
|
|
||
| Subgraph Linter currently detects the following categories of issues: | ||
|
|
||
| - `entity-overwrite`: Detects cases where a handler works with an entity instance that becomes stale after calling a helper (or other code path) that loads and saves the same entity, and then the handler saves its stale instance and overwrites those updates. | ||
| - `unexpected-null`: Detects when entities may be saved in an invalid state—either because required fields weren’t initialized before `save()`, or because code attempts to assign to `@derivedFrom` fields. | ||
| - `unchecked-load`: Detects risky patterns where `Entity.load(...)` is treated as always present (for example via `!`) instead of explicitly handling the case where the entity doesn’t exist yet. | ||
| - `unchecked-nonnull`: Detects risky non-null assertions on values that can be missing at runtime, and encourages explicit guards instead of assuming the value is always set. | ||
| - `division-guard`: Detects divisions where the denominator may be zero on some execution paths, and suggests guarding the value before dividing. | ||
| - `derived-field-guard`: Detects cases where code updates “base” fields that require derived recomputation, but then saves without the helper(s) that keep derived values consistent. | ||
| - `helper-return-contract`: Detects helper functions that can return entities without fully initializing required fields, and flags call sites where the returned entity is used/saved without completing initialization. | ||
| - `undeclared-eth-call`: Detects contract calls made by a handler (including inside helpers it calls) that are not declared in the handler’s `calls:` block in `subgraph.yaml`, so you can add the declaration and align with Graph’s declared `eth_call` best practices. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole section might work after the tutorial
Devs usually want the "how-to" right away
| ### Configuration (severity overrides and suppression) | ||
|
|
||
| Subgraph Linter reads configuration from `subgraph-linter.config.json` (or the file passed via `--config`). | ||
|
|
||
| The two main configuration features are: | ||
|
|
||
| 1. **Severity overrides** (treat certain checks as warnings or errors) | ||
| 2. **Comment-based suppression** (allow silencing diagnostics in exceptional cases) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They might want to first know why they might want to use this (but if I'm wrong diregard)
|
|
||
| *Configuration note:* Subgraph Linter supports configurable severities per check. By default, checks have sensible severities, but you can override them to match your project’s tolerance. Only checks with effective severity `error` cause a non-zero exit code; warnings-only runs exit successfully. | ||
|
|
||
| ### Configuration (severity overrides and suppression) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### Configuration (severity overrides and suppression) | |
| #### Configuration (severity overrides and suppression) |
| } | ||
| ``` | ||
|
|
||
| ### Suppressing a warning or error with a comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### Suppressing a warning or error with a comment | |
| #### Suppressing a warning or error with a comment |
Adds a new guide documenting Subgraph Linter, a static analysis tool for subgraphs.
Includes: