# Keep generated comments in sync with the code

Check the promises in an agent’s comments against return values, errors, and side effects.

Source: https://perchscan.com/examples/code-comment-rules/
Published: 2026-09-20

```python
def load_order(path):
    """Read one order from disk. Raises if the file is missing or malformed."""
    try:
        with open(path) as handle:
            return json.load(handle)
    except Exception:
        log.exception("could not read %s", path)
        return {}
```

The docstring says this function raises an exception, but the code catches the exception and returns an empty dictionary instead. This deliberately broken function comes from the [example order service](https://github.com/lakeday-org/perch/blob/50860211516249122087f9da706b99452225c030/test/fixtures/order-service/storage.py).

## Check the comment against the code

First [set up the example project](/examples/defect-scans/#run-the-example), then save this rule in `perch.yaml`:

```yaml
- name: comments-match-behavior
  where: "**/*.{py,js,ts}"
  each: method
  ensure: >-
    The method's leading comment accurately describes its
    return values, errors, and side effects. Promising an
    exception that is swallowed, an unchanged input that is
    mutated, or a return type the body does not produce
    breaks this rule. A method without a leading comment
    satisfies this rule.
```

```sh
perch check storage.py::load_order --rules comments-match-behavior
```

The fix depends on which behavior the callers need. If they rely on the exception, remove the catch or re-raise after logging. If a missing file should return an empty value, change the docstring to say so, and keep parse errors distinguishable where callers need to tell them apart.

## TypeScript example

The same rule catches a comment that promises not to modify its input when the code does. Save this illustrative function as `sort.ts`:

```typescript
/** Return sorted IDs without modifying the caller's array. */
export function sortedIds(ids: number[]): number[] {
  return ids.sort((a, b) => a - b);
}
```

```sh
perch check sort.ts::sortedIds --rules comments-match-behavior
```

`sort` changes the caller's array in place. Sorting a copy with `[...ids].sort((a, b) => a - b)` does what the comment says. Add a test that checks both the returned order and the original array.

## Useful comments

A second rule checks whether a comment tells the reader anything the code does not:

```yaml
- name: comments-add-information
  where: "src/**/*.{py,js,ts}"
  each: method
  ensure: >-
    If the method has a leading comment, it explains a caller
    contract, a constraint, or a reason for a non-obvious
    choice. Only restating the method name or narrating the
    next statement breaks this rule. A simple method with no
    leading comment satisfies this rule.
```

`perch scan --filter type=docs` asks the built-in questions about method documentation. For requirements specific to your codebase, write your own `lint` rules. Neither one expects a comment on every trivial function.
