badness 0.11.0

A language server, formatter, and linter for LaTeX
<!-- Generated by `cargo run --example docgen`. Do not edit by hand: edit each rule's `description()`/`examples()` in `src/bib/linter/rules/` and regenerate. -->

# BibTeX Linter Rules

`badness lint` runs a parallel set of built-in rules over each `.bib` file's
parse tree and reports a diagnostic for every finding. This page is the
catalogue: one section per rule, keyed by its stable **rule id**. Bib rules
share one id namespace with the [LaTeX rules](linter-rules.md), so the same
`[lint]` `select`/`ignore` (and `--select`/`--ignore`) target both.

Every rule is **on by default**; narrowing happens only through `select`/`ignore`
in the `[lint]` table (see the
[Configuration reference](configuration.md#lint)). Where a rewrite is unambiguous a rule
carries an **auto-fix**: a *safe* fix (shown below as "After applying the fix")
is applied by `badness lint --fix`.

Each example below is linted live to produce its diagnostic and fixed output, so
this page never drifts from the rules' actual behavior.

## `duplicate-key`

Flag a cite key defined by more than one entry in the same `.bib` file. Keys are compared case-insensitively, matching BibTeX, which silently keeps only one of the colliding entries; every definition after the first is flagged. No autofix: resolving the collision (rename vs delete) is the author's call.

The same cite key defined by two entries:

```bib
@misc{knuth84, title = {Draft}}
@book{knuth84, title = {Book}}
```

```text
warning: duplicate-key
 --> references.bib:2:7
  |
2 | @book{knuth84, title = {Book}}
  |       ^^^^^^^ cite key `knuth84` is defined more than once
```

## `missing-required-field`

Flag a regular entry lacking a field its type requires, per the biblatex data model. An alternation like `date` *or* `year` is satisfied by either, and classic-BibTeX aliases count (`journal` satisfies `journaltitle`). An entry type the built-in database does not know carries no signature and is never flagged. Report-only -- field content cannot be invented.

An `@article` without its required `journaltitle`:

```bib
@article{doe2020,
  author = {Doe, Jane},
  title  = {A study},
  year   = 2020
}
```

```text
warning: missing-required-field
 --> references.bib:1:10
  |
1 | @article{doe2020,
  |          ^^^^^^^ entry `article` is missing required field `journaltitle`
```

## `unknown-field`

Flag a field that is neither required nor optional for its entry type and carries no global field metadata -- usually a typo, or data misplaced from another entry type. BibLaTeX silently ignores fields it does not know, so the mistake otherwise vanishes without a trace. Only entry types the built-in database knows are checked. Report-only -- deleting the field would discard data.

A typo'd field name (`pubisher` for `publisher`):

```bib
@book{turing50,
  author   = {Turing, Alan},
  title    = {A book},
  pubisher = {Elsevier},
  year     = 1950
}
```

```text
warning: unknown-field
 --> references.bib:4:3
  |
4 |   pubisher = {Elsevier},
  |   ^^^^^^^^ unknown field `pubisher` on `book` entry
```

## `empty-field`

Flag a field whose value is empty or whitespace-only (`title = {}`, `note = ""`). An empty field carries no data, and some styles still emit punctuation around it. The safe autofix deletes the field along with its separating comma.

An empty `note` left behind by an edit:

```bib
@misc{knuth84,
  title = {Draft},
  note  = {}
}
```

```text
warning: empty-field
 --> references.bib:3:3
  |
3 |   note  = {}
  |   ^^^^^^^^^^ field `note` is empty
```

After applying the fix:

```bib
@misc{knuth84,
  title = {Draft}
}
```

## `duplicate-field`

Flag a field name appearing more than once on a single entry (names compared case-insensitively). BibTeX and Biber keep only one occurrence and silently discard the rest, so a duplicate is almost always a merge or copy-paste mistake; every occurrence after the first is flagged. When the repeated value is byte-identical to the kept one, a safe autofix deletes the redundant copy; when the values differ, which one wins is engine-dependent, so the finding is report-only.

Two `note` fields with identical values -- deleting the redundant copy is safe:

```bib
@misc{knuth84,
  note = {Draft},
  note = {Draft}
}
```

```text
warning: duplicate-field
 --> references.bib:3:3
  |
3 |   note = {Draft}
  |   ^^^^ duplicate field `note` on `misc` entry
```

After applying the fix:

```bib
@misc{knuth84,
  note = {Draft}
}
```

Differing values are report-only (which copy the engine keeps is style-dependent, so dropping either would change meaning):

```bib
@misc{knuth84,
  note = {First draft},
  note = {Second draft}
}
```

```text
warning: duplicate-field
 --> references.bib:3:3
  |
3 |   note = {Second draft}
  |   ^^^^ duplicate field `note` on `misc` entry
```

## `unused-string`

Flag an `@string` macro defined in the file but never referenced by any field value. For the common self-contained `.bib` an unused macro is dead weight; in a multi-file bibliography it may be referenced from another `.bib`, so treat cross-file setups with care -- cross-file `@string` resolution is not modeled yet. Report-only: deleting a definition is a meaning-level edit left to the author.

A defined macro no field value references:

```bib
@string{cup = {Cambridge University Press}}
@book{turing50, title = {Draft}, publisher = {Springer}}
```

```text
warning: unused-string
 --> references.bib:1:9
  |
1 | @string{cup = {Cambridge University Press}}
  |         ^^^ `@string` macro `cup` is defined but never used
```

## `undefined-string`

Flag an `@string` macro used in a field value but defined nowhere in the file (the twelve month macros `jan`..`dec` are predefined). Usually a typo'd macro name or a missing `@string` definition; BibTeX errors on it at build time. In a multi-file bibliography the definition may live in another `.bib`, so a use resolved there is a false positive -- cross-file `@string` resolution is not modeled yet. Report-only: the fix (define the macro or correct the name) is a meaning-level edit left to the author.

A typo'd macro name (`cpu` for `cup`):

```bib
@string{cup = {Cambridge University Press}}
@book{turing50, title = {Draft}, publisher = cpu}
```

```text
warning: undefined-string
 --> references.bib:2:46
  |
2 | @book{turing50, title = {Draft}, publisher = cpu}
  |                                              ^^^ `@string` macro `cpu` is used but never defined
```

## `title-capitalization`

Flag an unprotected acronym or mid-word capital in a title-like field (`title`, `booktitle`, `journaltitle`, ...). Many bibliography styles lowercase unprotected title text, so `DNA` renders as `dna` unless written `{DNA}`. Flagged are runs of two or more capitals and the camelCase brand pattern (a first capital mid-way through a lowercase-initial word, like `iPhone`); ordinary Title Case, name particles (`McDonald`), and mixed-case tokens (`LaTeX`) stay quiet, as does anything already inside a `{...}` group. Report-only -- choosing what to protect is the author's call.

An unprotected acronym a title-lowercasing style would render as `dna`:

```bib
@article{watson53, title = {Molecular structure of DNA}}
```

```text
warning: title-capitalization
 --> references.bib:1:52
  |
1 | @article{watson53, title = {Molecular structure of DNA}}
  |                                                    ^^^ unprotected capitals `DNA` in `title`; wrap in braces (`{DNA}`) to keep case under title-lowercasing styles
```

## `encoding-hints`

Surface non-ASCII text in a field value as a hint (accented text is perfectly valid in a UTF-8 setup, hence not a warning). Raw non-ASCII renders correctly only when the file is UTF-8 and the document loads a matching input encoding (`inputenc` with pdfLaTeX, `fontspec` with Xe/LuaLaTeX); legacy toolchains may mangle it. Either confirm the encoding or use a LaTeX escape (`\'e` for `é`). Report-only -- the right fix depends on the project's toolchain.

An accented name entered as raw UTF-8:

```bib
@article{erdos47, author = {Erdős, Paul}}
```

```text
help: encoding-hints
 --> references.bib:1:32
  |
1 | @article{erdos47, author = {Erdős, Paul}}
  |                                ^ non-ASCII text `ő`; ensure the file is UTF-8 and the document loads an input encoding (inputenc/fontspec), or use a LaTeX escape
```

## Suppression

BibTeX has no line-comment token, so per-site suppression rides a structured
`@comment` entry instead of the LaTeX `%` directive. A plain directive
suppresses one rule on the **next entry**:

```bib
@comment{badness-ignore missing-required-field: publisher long gone}
@book{oldbook, title = {An Orphaned Book}}
```

`@comment{badness-ignore-file <id>: ...}` suppresses one rule file-wide, and
`@comment{badness-ignore-file: ...}` suppresses all rules file-wide. Parse
diagnostics (rule id `parse`) are never suppressed.