Skip to content

Fix enum convertor returning None for already-converted values#1563

Open
bysiber wants to merge 2 commits intofastapi:masterfrom
bysiber:fix/enum-convertor-double-conversion
Open

Fix enum convertor returning None for already-converted values#1563
bysiber wants to merge 2 commits intofastapi:masterfrom
bysiber:fix/enum-convertor-double-conversion

Conversation

@bysiber
Copy link

@bysiber bysiber commented Feb 20, 2026

Summary

generate_enum_convertor silently returns None when it receives a value that's already an enum member. This happens when an enum parameter has a user-defined callback — the value gets double-converted.

The Bug

The enum convertor builds a lookup map from str(val.value) for each member, then looks up incoming values using str(value). When the value is already an enum member (e.g., Network.conv), str(Network.conv) returns "Network.conv" — which doesn't match any key in val_map (which contains "conv"). The convertor falls through and implicitly returns None.

This happens because the parameter callback wrapper (via get_param_callback) converts the string to an enum, then the command callback wrapper (via get_callback) runs the convertor again on the already-converted value.

from enum import Enum
from typing import Annotated
import typer

class Network(Enum):
    simple = "simple"
    conv = "conv"

app = typer.Typer()

def validate(value: Network) -> Network:
    return value

@app.command()
def main(network: Annotated[Network, typer.Option(callback=validate)] = Network.simple):
    print(f"Got: {network!r}")  # Prints: Got: None

app()

The Fix

Added an isinstance guard to return the value as-is when it's already an enum member — the same pattern used by param_path_convertor a few lines above.

When an enum parameter has a user callback, the value gets converted
twice: once in the parameter callback wrapper and again in the command
callback wrapper. The second pass receives an enum member, but
str(EnumMember) returns 'ClassName.member' which doesn't match the
val_map keys, so the convertor silently returns None.

Added an isinstance check (same pattern as param_path_convertor) to
pass through values that are already enum members.
@svlandeg svlandeg added the bug Something isn't working label Feb 20, 2026
@svlandeg
Copy link
Member

Hi, thanks for the PR! Could you look into the failing CI? I'll put this in draft in the meantime 🙏

@svlandeg svlandeg marked this pull request as draft February 20, 2026 10:42
@bysiber
Copy link
Author

bysiber commented Feb 20, 2026

Added a test for the newly covered branch — it checks that passing an already-converted enum member through the convertor returns it unchanged. CI should be green now.

@svlandeg svlandeg marked this pull request as ready for review February 20, 2026 11:37
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