Beacon Linter

The Beacon Rule Engine is a modular static analysis system powering diagnostics in Beacon.

It's foundationally a pure Rust implementation of PyFlakes.


Legend: ⚠ = Warning ✕ = Error ⓘ = Info

CodeName / RuleKindLevelCategoryDescription
BEA001UndefinedNameNamingVariable or function used before being defined.
BEA002DuplicateArgumentFunctionsDuplicate parameter names in a function definition.
BEA003ReturnOutsideFunctionFlowreturn statement outside of a function or method body.
BEA004YieldOutsideFunctionFlowyield or yield from used outside a function context.
BEA005BreakOutsideLoopFlowbreak used outside a for/while loop.
BEA006ContinueOutsideLoopFlowcontinue used outside a for/while loop.
BEA007DefaultExceptNotLastExceptionA bare except: is not the final exception handler in a try block.
BEA008RaiseNotImplementedSemanticsUsing raise NotImplemented instead of raise NotImplementedError.
BEA009TwoStarredExpressionsSyntaxTwo or more * unpacking expressions in assignment.
BEA010TooManyExpressionsInStarredAssignmentSyntaxToo many expressions when unpacking into a starred target.
BEA011IfTupleLogicA tuple literal used as an if condition — always True.
BEA012AssertTupleLogicAssertion always true due to tuple literal.
BEA013FStringMissingPlaceholdersStringsf-string declared but contains no {} placeholders.
BEA014TStringMissingPlaceholdersStringst-string declared but contains no placeholders.
BEA015UnusedImportSymbolsImport is never used within the file.
BEA016UnusedVariableSymbolsLocal variable assigned but never used.
BEA017UnusedAnnotationSymbolsAnnotated variable never referenced.
BEA018RedefinedWhileUnusedNamingVariable redefined before original was used.
BEA019ImportShadowedByLoopVarScopeImport name shadowed by a loop variable.
BEA020ImportStarNotPermittedImportsfrom module import * used inside a function or class.
BEA021ImportStarUsedImportsimport * prevents detection of undefined names.
BEA022UnusedIndirectAssignmentNamingGlobal or nonlocal declared but never reassigned.
BEA023ForwardAnnotationSyntaxErrorTypingSyntax error in forward type annotation.
BEA024MultiValueRepeatedKeyLiteralDictDictionary literal repeats key with different values.
BEA025PercentFormatInvalidFormatStringsInvalid % format string.
BEA026IsLiteralLogicComparing constants with is or is not instead of ==/!=.
BEA027DefaultExceptNotLastExceptionBare except: must appear last.
BEA028UnreachableCodeFlowCode after a return, raise, or break is never executed.
BEA029RedundantPassCleanuppass used in a block that already has content.
BEA030EmptyExceptExceptionexcept: with no handling code (silent failure).

Rules

BEA001

Example

print(foo) before foo is defined.

Fix

Define the variable before use or fix the typo.

BEA002

Example

def f(x, x):
    pass

Fix

Rename one of the parameters.

BEA003

Example

Top-level return 5 in a module.

Fix

Remove or move inside a function.

BEA004

Example

yield x at module scope.

Fix

Wrap in a generator function.

BEA005

Example

break in global scope or in a function without loop.

Fix

Remove or restructure the code to include a loop.

BEA006

Example

continue in a function with no loop.

Fix

Remove or replace with control flow logic.

BEA007

Example

except: followed by except ValueError:

Fix

Move the except: block to the end of the try.

BEA008

Example

raise NotImplemented

Fix

Replace with raise NotImplementedError.

BEA009

Example

a, *b, *c = d

Fix

Only one starred target is allowed.

BEA010

Example

a, b, c, d = (1, 2, 3)

Fix

Adjust unpacking count.

BEA011

Example

if (x,):
    ...

Fix

Remove accidental comma or rewrite condition.

BEA012

Example

assert (x, y)

Fix

Remove parentheses or fix expression.

BEA013

Example

f"Hello world"

Fix

Remove the f prefix if unnecessary.

BEA014

Example

t"foo"

Fix

Remove the t prefix if unused.

BEA015

Example

import os not referenced.

Fix

Remove the unused import.

BEA016

Example

x = 10 never referenced again.

Fix

Remove assignment or prefix with _ if intentional.

BEA017

Example

x: int declared but unused.

Fix

Remove or use variable.

BEA018

Example

x = 1; x = 2 without reading x.

Fix

Remove unused definition.

BEA019

Example

import os
for os in range(3):
    ...

Fix

Rename loop variable.

BEA020

Example

def f():
    from math import *

Fix

Move import to module level.

BEA021

Example

from os import *

Fix

Replace with explicit imports.

BEA022

Example

global foo never used.

Fix

Remove redundant declaration.

BEA023

Example

def f() -> "List[int": ...

Fix

Fix or quote properly.

BEA024

Example

{'a': 1, 'a': 2}

Fix

Merge or remove duplicate keys.

BEA025

Example

"%q" % 3

Fix

Correct format specifier.

BEA026

Example

x is 5

Fix

Use ==/!=.

BEA027

Example

As above.

Fix

Reorder exception handlers.

BEA028

Example

return 5; print("unreachable")

Fix

Remove or refactor code.

BEA029

Example

def f():
    pass
    return 1

Fix

Remove redundant pass.

BEA030

Example

try:
    ...
except:
    pass

Fix

Handle exception or remove block.

Planned

NameKindCategorySeverityRationale
Mutable Default ArgumentMutableDefaultArgumentSemanticDetect functions that use a mutable object (e.g., list, dict, set) as a default argument.
Return in FinallyReturnInFinallyFlowCatch a return, break, or continue inside a finally block: this often suppresses the original exception and leads to subtle bugs.
For-Else Without BreakForElseWithoutBreakFlowThe for ... else construct where the else never executes a break is confusing and often mis-used. If you have else: on a loop but never break, you may signal confusing logic.
Wrong Exception CaughtBroadExceptionCaughtExceptionCatching too broad exceptions (e.g., except Exception: or except:) instead of specific types can hide bugs. You already have empty except; this expands to overly broad catching.
Inconsistent Return TypesInconsistentReturnTypesFunctionA function that returns different types on different paths (e.g., return int in one branch, return None in another) may lead to consuming code bugs especially if not annotated.
Index / Key Errors LikelyUnsafeIndexOrKeyAccessDataDetect patterns that likely lead to IndexError or KeyError, e.g., accessing list/dict without checking length/keys, especially inside loops.
Unused Coroutine / Async FunctionUnusedCoroutineSymbolIn async code: a async def function is defined but neither awaited nor returned anywhere — likely a bug.
Resource Leak / Unclosed DescriptorUnclosedResourceSymbolDetect file or network resource opened (e.g., open(...)) without being closed or managed via context manager (with).
Logging Format String ErrorsLoggingFormatErrorStringUsing % or f-string incorrectly in logging calls (e.g., logging format mismatches number of placeholders) can cause runtime exceptions or silent failures.
Comparison to None Using == / !=NoneComparisonLogicDiscourage == None or != None in favor of is None / is not None.