Main Ecosystems
HomePython CorePandas ReferenceNumPy ScientificFastAPI & PydanticDjango Enterprise
More Ecosystems
Environment & SetupRequests & HTTPAsyncIO ConcurrencyObject-Oriented OOPPyTorch Deep LearningScikit-Learn MLFlask FrameworkWeb ScrapingDatabase & ORMDevOps & Docker

Pyright Type Incompatibility Error in Python

Verified FixPython 3.10+Pyright 1.1+ / Python 3.10+Silo: core

Quick Fix / Solution Rapide

Align static type annotations using Union / |, refine function argument types with isinstance() type narrowing, or apply # type: ignore for intentional dynamic patterns.

Root Cause Analysis

This error occurs when a static type checker (such as Pyright, Pylance in VS Code, or Mypy) analyzes Python source code and detects that the inferred type of an expression does not satisfy the type constraints declared by the receiving parameter or variable annotation.

1. Static Type Checking vs Dynamic Runtime Execution

Python is dynamically typed at runtime, but modern IDEs use static analyzers like Pyright to catch bugs before execution. When a function annotates a parameter as int and callers pass a string (or str | int), Pyright flags Type 'str' cannot be assigned to type 'int'.

2. Invariant Container Types (list[Derived] vs list[Base])

In Python typing, mutable containers like list and dict are invariant. Passing a list[int] to a function expecting list[float] fails type checking even though integers are numerically compatible with floats.

3. Missing None Checks (Optional Types)

When a variable has type Optional[str] (or str | None), calling string methods like .lower() without an if val is not None: guard causes Pyright to flag Cannot access attribute 'lower' for type 'None'.

4. Overloaded Function Signatures

Complex functions returning different types depending on input flags require @overload decorators for Pyright to resolve return types precisely.

Reproduction Code (MCVE)

Example: Bug Reproduction
def format_account_id(account_id: int) -> str:
    if not isinstance(account_id, int):
        raise TypeError(f'Type incompatibility error: expected int, got {type(account_id).__name__}')
    return f'ACC-{account_id:06d}'

# Passing str argument violates type annotation
format_account_id('98765')

Solution 1: Broaden Annotations with Union or Type Narrowing

Use int | str union types in Python 3.10+ and apply isinstance() checks to narrow types safely.

Example: Recommended Solution
def format_account_id(account_id: int | str) -> str:
    if isinstance(account_id, str):
        account_id = int(account_id)
    return f'ACC-{account_id:06d}'

print(format_account_id(12345))
print(format_account_id('67890'))

Solution 2: Use Sequence for Covariant Read-Only Containers

Annotate function parameters with collections.abc.Sequence or Iterable instead of list to allow subtype compatibility.

Example: Alternative Solution
from collections.abc import Sequence

def calculate_total(values: Sequence[float]) -> float:
    return sum(values)

int_list: list[int] = [10, 20, 30]
print(f'Total: {calculate_total(int_list)}')

A common mistake is using Any everywhere to silence type errors. While Any suppresses Pyright warnings, it disables all type safety benefits throughout downstream code. Prefer object for truly unknown inputs combined with isinstance() checks, or TypeVar for generic functions. Edge cases occur with Pydantic models: use pydantic.BaseModel fields rather than raw dictionary lookups to ensure automatic type validation. Contrast this static warning with runtime TypeError: unhashable type, which occurs when using mutable objects as dictionary keys.