Skip to content

Fix Option(None) in Annotated crashing with AttributeError#1564

Open
bysiber wants to merge 1 commit intofastapi:masterfrom
bysiber:fix/annotated-option-none-crash
Open

Fix Option(None) in Annotated crashing with AttributeError#1564
bysiber wants to merge 1 commit intofastapi:masterfrom
bysiber:fix/annotated-option-none-crash

Conversation

@bysiber
Copy link

@bysiber bysiber commented Feb 20, 2026

Summary

Using Annotated[str, typer.Option(None)] crashes with AttributeError: 'NoneType' object has no attribute 'isidentifier'.

The Bug

In utils.py, when processing Annotated parameters, typer reinterprets Option's first positional argument from "default value" to "first param_decl name". The guard only checks parameter_info.default is not ..., which passes for None since None is not ... is True. The None value then gets cast(str, ...) and inserted into param_decls, and Click crashes when it tries to call .isidentifier() on it.

from typing import Annotated
import typer

app = typer.Typer()

@app.command()
def main(name: Annotated[str, typer.Option(None)] = "world"):
    print(f"Hello {name}")

app()
# AttributeError: 'NoneType' object has no attribute 'isidentifier'

The Fix

Added isinstance(parameter_info.default, str) to the guard so only actual strings are treated as param_decl names. Non-string values (like None) are left as default and handled by the normal default-value logic below.

When using Annotated[str, Option(None)], the None default gets
reinterpreted as a param_decl name since 'None is not ...' is True.
Click then crashes calling .isidentifier() on None.

Added an isinstance(str) check so only actual strings are treated
as param_decl names. Non-string defaults are left as-is.
@svlandeg svlandeg added the bug Something isn't working label Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants