Skip to content

Diagnostics

When rigor check finds a problem it reports a diagnostic: a file, a line and column, a severity, a rule ID, and a message. This page is the reference for the rule catalogue, the severity model, and suppression. For the reasoning behind each rule, see handbook chapter 8.

Every rule has a two-segment family.rule identifier:

FamilyCovers
callCall sites — undefined methods, arity, argument types, nil receivers.
flowControl-flow proofs — always-raises, dead branches, constant conditions.
defMethod definitions — return types, ivar writes, visibility.
assertassert_type checks.
dumpdump_type notices.

rigor explain <rule> prints the full catalogue entry for any ID; rigor explain with no argument lists them all.

RuleFires when
call.undefined-methodThe method is not defined on the receiver’s statically known class.
call.wrong-arityThe positional-argument count matches no signature.
call.argument-type-mismatchAn argument’s type provably violates the parameter contract.
call.possible-nil-receiverThe receiver is T | nil and the method is not defined on NilClass.
call.unresolved-toplevelA top-level implicit-self call resolves against no same-file def, pre_eval: patch, or Kernel / Object method.
flow.always-raisesThe expression provably raises on every reachable path.
flow.unreachable-branchAn if / unless / ternary branch is statically dead.
flow.always-truthy-conditionA condition is provably always truthy or always falsey.
flow.dead-assignmentA local is written but never read in the same method.
def.return-type-mismatchThe method body’s result violates its declared RBS return type.
def.ivar-write-mismatchAn instance variable is written with a type disagreeing with its first write.
def.method-visibility-mismatchAn explicit-receiver call reaches a private method.
def.override-visibility-reducedAn override reduces the visibility it inherits from a project-defined ancestor.
def.override-return-widenedAn override’s declared return type widens the inherited return (covariance).
def.override-param-narrowedAn override narrows an inherited parameter type (contravariance).
assert.type-mismatchAn assert_type expectation does not match the inferred type.
dump.typeA dump_type call — informational, prints the inferred type.

Plugins may contribute further families and rules; rigor explain lists whatever the active configuration loads.

Each rule emits with an authored severity, then a profile re-stamps it for the run. Three profiles, set with the severity_profile: config key:

ProfileStance
lenientOnly proven diagnostics are errors; uncertain ones drop to warning / info. For incremental adoption on legacy code.
balanced (default)Most rules error; dump.type info; uncertain rules warning.
strictEvery rule is an error. CI-friendly.

For finer control, severity_overrides: maps a rule ID or a family to one of error, warning, info, or off:

severity_profile: balanced
severity_overrides:
flow.always-truthy-condition: off
call: warning

A rule-specific override beats a family override.

Three layers, from narrowest to broadest.

In-source, one line. A trailing comment suppresses the named rules on that line:

config.merge(extra) # rigor:disable call.undefined-method

It accepts qualified IDs, family wildcards (call), a comma- or space-separated list, or all.

In-source, whole file. # rigor:disable-file <rules> anywhere in a file suppresses those rules for every line; # rigor:disable-file all silences the file.

Project-wide. The disable: config key turns rules off across the whole run:

disable:
- flow.dead-assignment

For a known backlog you want to keep visible but not fail on, prefer a baseline over a blanket disable:disable: also hides any new occurrences.

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.