Skip to content

RecursionError when using pydantic field examples None #190

@migduroli

Description

@migduroli

Summary

A RecursionError occurs during the OpenAPI schema generation process when a pydantic.BaseModel contains a field defined with examples=[None].

Reproduce steps

Description

A RecursionError occurs during the OpenAPI schema generation process when a pydantic.BaseModel contains a field defined with examples=[None].

This error happens at application startup when Flama inspects the routes and their associated schemas. The error prevents the schema for any endpoint using the problematic model from being generated correctly. As a consequence, the entire endpoint is absent from the documentation UI at /docs.

The issue is specifically triggered by the presence of None as an item within the examples list of a pydantic.Field. Other literal examples like examples=[1] or examples=["example"] work as expected.

Steps to Reproduce

The following minimal, self-contained application reproduces the error.

  1. Save the code below as app.py:
    import typing as t
    import pydantic
    import flama
    from flama import Flama, schemas
    
    app = Flama(
        openapi={
            "info": {
                "title": "Puppy Register",
                "version": "0.1",
                "description": "A register of puppies",
            }
        },
        schema="/schema/",
        docs="/docs/",
    )
    
    
    class Puppy(pydantic.BaseModel):
        # The line below is the specific trigger for the bug.
        # Removing `examples=[None]` makes the app work correctly.
        id: int | None = pydantic.Field(..., examples=[None])
        name: str
        age: int
    
    app.schema.register_schema("Puppy", Puppy)
    
    
    def list_puppies(name: t.Optional[str] = None) -> t.Annotated[list[schemas.SchemaType], schemas.SchemaMetadata(Puppy)]:
        ...
    
    
    def create_puppy(
        puppy: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(Puppy)],
    ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(Puppy)]:
        ...
    
    
    app.add_route("/puppy/", list_puppies, methods=["GET"])
    app.add_route("/puppy/", create_puppy, methods=["POST"])
    
    if __name__ == "__main__":
        flama.run(flama_app=app, server_host="0.0.0.0", server_port=8080)
  2. Run the application.
  3. Observe the RecursionError in the console during startup.
  4. If you try to access the docs at http://127.0.0.1:8080/docs/, you will see that the /puppy/ endpoints are missing.

Expected Behavior

The application should start without any errors. The OpenAPI schema should be generated successfully. The /puppy/ endpoints (both GET and POST) should be visible and correctly documented in the /docs UI. The id field in the Puppy schema should be correctly marked as nullable and its documentation should include null as one of the possible example values.

Actual Behavior

The application fails to start and raises a RecursionError: maximum recursion depth exceeded. A traceback originating from Flama's schema generation logic is printed to the console.

Because of this fatal error during the schema inspection phase, the affected /puppy/ routes are not included in the generated OpenAPI schema, and therefore they do not appear on the /docs/ page at all.

Schema library

Pydantic

Models library

None

Error logs

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions