Skip to main content
Mypy can display error codes like [attr-defined] after each error message. Error codes allow you to selectively silence or enable specific types of errors.

Understanding error codes

Error codes serve two main purposes:

Selective silencing

Use # type: ignore[code] to ignore specific errors without suppressing other important errors.

Documentation

Error codes link to documentation explaining why the error occurred and how to fix it.

Displaying error codes

By default, error codes are shown in error messages:
mypy program.py
program.py:12: error: "str" has no attribute "append"  [attr-defined]
program.py:15: error: Argument 1 to "process" has incompatible type "int"; expected "str"  [arg-type]
To hide error codes:
mypy --hide-error-codes program.py
To show documentation links:
mypy --show-error-code-links program.py

Silencing specific error codes

Per-line silencing

Use # type: ignore[code] to silence specific errors on a line:
from foolib import foo  # type: ignore[attr-defined]
Avoid using # type: ignore without error codes, as it suppresses all errors on that line.

Global enabling/disabling

Use command-line flags to enable or disable error codes globally:
# Enable optional error codes
mypy --enable-error-code truthy-bool,ignore-without-code src/

# Disable specific error codes
mypy --disable-error-code misc,no-untyped-def src/
In configuration files:
[mypy]
enable_error_code = truthy-bool, ignore-without-code, unused-awaitable
disable_error_code = misc

Per-module configuration

Configure error codes for specific modules:
[mypy]
enable_error_code = truthy-bool, ignore-without-code

[mypy-tests.*]
disable_error_code = no-untyped-def, no-untyped-call

[mypy-legacy.*]
disable_error_code = arg-type, return-value

Per-file configuration

Use inline comments at the top of a file:
# mypy: enable-error-code="truthy-bool, ignore-without-code"
# mypy: disable-error-code="misc"

def validate(items: list[str]) -> bool:
    if items:  # Warning: list is always truthy
        return True
    return False

Common error codes

Here are the most frequently used error codes from Mypy’s source:

Type errors

attr-defined
error code
Check that attribute exists.
name = "hello"
name.append("world")  # error: "str" has no attribute "append"  [attr-defined]
name-defined
error code
Check that name is defined.
print(undefined_var)  # error: Name "undefined_var" is not defined  [name-defined]
call-arg
error code
Check number, names, and kinds of arguments in calls.
def greet(name: str) -> None:
    print(f"Hello, {name}")

greet()  # error: Missing positional argument "name" in call  [call-arg]
arg-type
error code
Check argument types in calls.
def process(x: int) -> None:
    pass

process("hello")  # error: Argument 1 has incompatible type "str"; expected "int"  [arg-type]
return-value
error code
Check that return value is compatible with signature.
def get_number() -> int:
    return "not a number"  # error: Incompatible return value type  [return-value]
assignment
error code
Check that assigned value is compatible with target.
x: int = "string"  # error: Incompatible types in assignment  [assignment]
index
error code
Check indexing operations.
data: dict[str, int] = {"a": 1}
value = data[0]  # error: Invalid index type "int" for "dict[str, int]"  [index]
operator
error code
Check that operator is valid for operands.
result = "hello" + 123  # error: Unsupported operand types  [operator]

Import errors

import
error code
Require that imported module can be found or has stubs.
import nonexistent_module  # error: Cannot find implementation or library stub  [import]
import-not-found
error code
Require that imported module can be found. (Subcode of import)
import missing_package  # error: Cannot find implementation  [import-not-found]
import-untyped
error code
Require that imported module has stubs. (Subcode of import)
import untyped_library  # error: Library stubs not installed  [import-untyped]

Definition errors

no-untyped-def
error code
default:"Disabled"
Check that every function has type annotations.
def calculate(x, y):  # error: Function is missing a type annotation  [no-untyped-def]
    return x + y
Enable with: --disallow-untyped-defs or --enable-error-code no-untyped-def
no-untyped-call
error code
default:"Disabled"
Disallow calling untyped functions from typed functions.
def untyped(x, y):
    return x + y

def typed(a: int, b: int) -> int:
    return untyped(a, b)  # error: Call to untyped function  [no-untyped-call]
Enable with: --disallow-untyped-calls or --enable-error-code no-untyped-call
var-annotated
error code
Require variable annotation if type can’t be inferred.
items = []  # error: Need type annotation for "items"  [var-annotated]

Optional error codes

These error codes are disabled by default and must be explicitly enabled:
redundant-cast
error code
default:"Disabled"
Check that cast changes type of expression.
from typing import cast

x: int = 5
y = cast(int, x)  # error: Redundant cast  [redundant-cast]
Enable with: --warn-redundant-casts or --enable-error-code redundant-cast
comparison-overlap
error code
default:"Enabled"
Check that types in comparisons overlap.
x: int = 5
if x == "hello":  # error: Non-overlapping equality check  [comparison-overlap]
    pass
unreachable
error code
default:"Disabled"
Warn about unreachable statements or expressions.
def example(x: int) -> str:
    if isinstance(x, str):  # Always false
        return x  # error: Statement is unreachable  [unreachable]
    return str(x)
Enable with: --warn-unreachable or --enable-error-code unreachable
truthy-bool
error code
default:"Disabled"
Warn about expressions always true in boolean contexts.
items: list[str] = ["a", "b"]
if items:  # error: List is always truthy  [truthy-bool]
    pass
Enable with: --enable-error-code truthy-bool
unused-ignore
error code
default:"Disabled"
Ensure that all # type: ignore comments are necessary.
x: int = 5  # type: ignore  # error: Unused "type: ignore" comment  [unused-ignore]
Enable with: --warn-unused-ignores or --enable-error-code unused-ignore
ignore-without-code
error code
default:"Disabled"
Warn about # type: ignore comments without error codes.
x = unknown_function()  # type: ignore  # error: "type: ignore" without code  [ignore-without-code]
Enable with: --enable-error-code ignore-without-code
unused-awaitable
error code
default:"Disabled"
Ensure that all awaitable values are used.
async def get_data() -> str:
    return "data"

async def process() -> None:
    get_data()  # error: Unused awaitable  [unused-awaitable]
Enable with: --enable-error-code unused-awaitable
possibly-undefined
error code
default:"Disabled"
Warn about variables defined only in some execution paths.
def example(flag: bool) -> None:
    if flag:
        x = 10
    print(x)  # error: Name "x" may be undefined  [possibly-undefined]
Enable with: --enable-error-code possibly-undefined
explicit-override
error code
default:"Disabled"
Require @override decorator for overridden methods.
from typing import override

class Base:
    def method(self) -> None: pass

class Derived(Base):
    def method(self) -> None:  # error: Missing @override  [explicit-override]
        pass
Enable with: --enable-error-code explicit-override

Error code subcodes

Some error codes are subcodes of broader codes. When you ignore a parent code, subcodes are also ignored:
  • import-not-found: Module implementation not found
  • import-untyped: Module stubs not found
# These both work:
import pkg  # type: ignore[import]
import pkg  # type: ignore[import-not-found]
  • method-assign: Assignment target is a method
class MyClass:
    def method(self) -> None: pass

obj = MyClass()
obj.method = lambda: None  # type: ignore[assignment]
# or: # type: ignore[method-assign]
  • typeddict-unknown-key: Unknown key in TypedDict
from typing import TypedDict

class Person(TypedDict):
    name: str

p: Person = {"name": "Alice", "age": 30}  # type: ignore[typeddict-item]
# or: # type: ignore[typeddict-unknown-key]

Configuration hierarchy

Error code configuration follows this precedence:
  1. Inline file configuration (# mypy: enable-error-code=...) - Highest
  2. Per-module config sections - Adjusts global settings
  3. Global configuration (command-line or config file) - Lowest
[mypy]
enable_error_code = truthy-bool, unused-awaitable

[mypy-tests.*]
disable_error_code = unused-awaitable

Best practices

# Good
import legacy  # type: ignore[import-not-found]

# Bad - suppresses ALL errors
import legacy  # type: ignore
Start with high-value codes and expand coverage:
[mypy]
# Phase 1: Basic strictness
enable_error_code = redundant-cast, unused-ignore

# Phase 2: More advanced
# enable_error_code = truthy-bool, ignore-without-code

# Phase 3: Comprehensive
# enable_error_code = unused-awaitable, possibly-undefined
[mypy]
enable_error_code = truthy-bool, ignore-without-code

[mypy-legacy.*]
disable_error_code = no-untyped-def, arg-type

[mypy-tests.*]
disable_error_code = no-untyped-def
# mypy: disable-error-code="misc"
# Reason: Generated file with complex type patterns
# TODO: Remove once generator supports proper type hints

Requiring error codes

Enable ignore-without-code to require error codes in all # type: ignore comments:
mypy --enable-error-code ignore-without-code src/
This helps maintain code quality by forcing developers to be explicit about which errors they’re ignoring:
# This will error:
from legacy import foo  # type: ignore  # error: "type: ignore" missing code  [ignore-without-code]

# This is OK:
from legacy import foo  # type: ignore[import-not-found]
Combine with --warn-unused-ignores to ensure all type ignores are necessary and properly scoped.

Build docs developers (and LLMs) love