{"id":164,"library":"beanie","title":"Beanie","description":"Async Python ODM for MongoDB built on Pydantic. Current version: 2.0.1 (Nov 2025). v2.0 breaking change: dropped Motor in favor of pymongo AsyncMongoClient. Requires Pydantic v2. Inner class Collection removed — use Settings instead. Must call init_beanie() before any document operations. Sync version is Bunnet (separate package).","status":"active","version":"2.0.1","language":"python","source_language":"en","source_url":"https://github.com/BeanieODM/beanie","tags":["beanie","mongodb","odm","async","pydantic","fastapi","python"],"install":[{"cmd":"pip install beanie","lang":"bash","label":"Python"}],"dependencies":[{"reason":"Required. Beanie v2.0+ uses pymongo AsyncMongoClient. Motor no longer required.","package":"pymongo","optional":false},{"reason":"Required. Beanie v2.0 requires Pydantic v2.","package":"pydantic","optional":false}],"imports":[{"note":"v2.0 dropped Motor. Use pymongo AsyncMongoClient. Inner class Collection removed — use Settings. LLMs trained pre-2025 generate Motor + Collection patterns.","wrong":"from motor.motor_asyncio import AsyncIOMotorClient  # v2: motor no longer needed\nfrom beanie import Document, init_beanie\n\nclass Product(Document):\n    name: str\n    class Collection:  # removed in v2 — use Settings\n        name = 'products'\n\nclient = AsyncIOMotorClient('mongodb://localhost')\nawait init_beanie(database=client.mydb, document_models=[Product])","symbol":"Document + init_beanie","correct":"from pymongo import AsyncMongoClient\nfrom beanie import Document, Indexed, init_beanie\nfrom pydantic import BaseModel\nfrom typing import Optional\n\nclass Category(BaseModel):\n    name: str\n\nclass Product(Document):\n    name: str\n    price: Indexed(float)\n    category: Optional[Category] = None\n\n    class Settings:  # v2 style — not Collection\n        name = 'products'\n\nasync def init():\n    client = AsyncMongoClient('mongodb://localhost:27017')\n    await init_beanie(\n        database=client.mydb,\n        document_models=[Product]\n    )"},{"note":"Must call init_beanie() before any Document operation. Query syntax uses Python operators (Product.price < 10.0), not raw MongoDB dicts.","wrong":"# Calling before init_beanie() raises RuntimeError\nproduct = await Product.find_one({'name': 'Widget'})","symbol":"CRUD operations","correct":"# All operations require init_beanie() to have been called first\n\n# Create\nproduct = await Product(name='Widget', price=9.99).insert()\n# or:\nproduct = await Product.insert_one(Product(name='Widget', price=9.99))\n\n# Find\nproducts = await Product.find(Product.price < 10.0).to_list()\nproduct = await Product.find_one(Product.name == 'Widget')\nproduct = await Product.get(product_id)  # by _id\n\n# Update\nawait product.set({Product.price: 12.99})\n# or:\nproduct.price = 12.99\nawait product.save()\n\n# Delete\nawait product.delete()"}],"quickstart":{"code":"# pip install beanie\nfrom pymongo import AsyncMongoClient\nfrom beanie import Document, Indexed, init_beanie\nfrom typing import Optional\nimport asyncio\n\nclass Product(Document):\n    name: str\n    price: Indexed(float)\n    in_stock: bool = True\n\n    class Settings:\n        name = 'products'  # MongoDB collection name\n\nasync def main():\n    client = AsyncMongoClient('mongodb://localhost:27017')\n    await init_beanie(database=client.shop, document_models=[Product])\n\n    # Insert\n    p = await Product(name='Widget', price=9.99).insert()\n    print(p.id)  # ObjectId\n\n    # Query\n    cheap = await Product.find(Product.price < 20.0).to_list()\n    one = await Product.find_one(Product.name == 'Widget')\n\n    # Update\n    await one.set({Product.price: 11.99})\n\n    # Delete\n    await one.delete()\n\nasyncio.run(main())","lang":"python","description":"Beanie v2.x quickstart with pymongo AsyncMongoClient."},"warnings":[{"fix":"from pymongo import AsyncMongoClient — not from motor.motor_asyncio import AsyncIOMotorClient","message":"Beanie v2.0 dropped Motor. Use pymongo AsyncMongoClient instead of AsyncIOMotorClient. Motor-based code breaks with ImportError or unexpected behavior.","severity":"breaking","affected_versions":">= 2.0"},{"fix":"class Settings: name = 'collection_name' — not class Collection: name = '...'","message":"Inner class Collection removed in v2. Use Settings instead. Collection still referenced in most tutorials and LLM-generated code.","severity":"breaking","affected_versions":">= 2.0"},{"fix":"Use @field_validator, model_config = ConfigDict(...) — Pydantic v2 patterns.","message":"Beanie v2.0 requires Pydantic v2. Pydantic v1 patterns (@validator, class Config) break. See pydantic registry entry for migration.","severity":"breaking","affected_versions":">= 2.0"},{"fix":"pip install bunnet — same API as beanie but sync.","message":"Sync usage removed in beanie. There is no sync version. Use Bunnet (pip install bunnet) for synchronous MongoDB access.","severity":"breaking","affected_versions":">= 1.x"},{"fix":"Call init_beanie() in FastAPI lifespan startup, not at module level.","message":"init_beanie() must be called before any Document operation. Calling Document.find() or Document.insert() before init raises RuntimeError. Common mistake in FastAPI startup.","severity":"gotcha","affected_versions":"all"},{"fix":"List every Document subclass in document_models=[Model1, Model2, ...]","message":"All document models must be passed to init_beanie(document_models=[...]). Missing a model means that model's collection is not configured — operations silently fail or error.","severity":"gotcha","affected_versions":"all"},{"fix":"Pass allow_index_dropping=True to init_beanie() in development to clean up. Leave False in production.","message":"allow_index_dropping defaults to False. Indexes are not deleted automatically when removed from model. Old indexes accumulate silently.","severity":"gotcha","affected_versions":"all"},{"fix":"Ensure the MongoDB server is running and accessible (e.g., on localhost:27017). Verify network connectivity, firewall rules, and the MongoDB server's bind IP configuration if it's not on the default address or port.","message":"The application is unable to connect to the MongoDB server, leading to a pymongo.errors.ServerSelectionTimeoutError during `init_beanie`. This often means MongoDB is not running, is inaccessible from the application's host, or is listening on a different address/port than expected.","severity":"gotcha","affected_versions":"all"},{"fix":"Ensure the MongoDB server is running and accessible from the application's environment on the configured host and port (e.g., 'localhost:27017' by default). Verify network connectivity and firewall rules if connecting to a remote server. The connection string (e.g., 'mongodb://localhost:27017') must be correct.","message":"Applications using Beanie (and PyMongo) will fail with ServerSelectionTimeoutError if the MongoDB server is not running or not accessible at the specified host and port. This is an environmental issue, not a Beanie API usage issue.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T09:11:49.968Z","next_check":"2026-06-24T00:00:00.000Z","problems":[{"fix":"Ensure that `await init_beanie(database=client.db_name, document_models=[YourDocumentClass])` is called at application startup, providing a valid Async PyMongo database instance and a list of all Document classes.","cause":"This error occurs when Beanie attempts to perform document operations (like find, insert, or update) before the `init_beanie()` function has been called, or if the relevant document models were not included in the `document_models` list during initialization.","error":"beanie.exceptions.CollectionWasNotInitialized"},{"fix":"Update your code to use `pymongo.AsyncMongoClient` directly and remove any explicit references to Motor's API, as Beanie v2.x handles the asynchronous client internally. Review the Beanie v2 migration guide for specific changes regarding the Motor to PyMongo Async API transition.","cause":"This error typically arises in Beanie v2.0.1 because the library transitioned from using Motor to `pymongo.AsyncMongoClient`, removing Motor-specific attributes and methods like `get_motor_collection`. This can also be seen when `fetch_links=True` is used with incompatible setups.","error":"AttributeError: get_motor_collection"},{"fix":"Ensure your `motor` and `beanie` versions are compatible. If using sessions, explicitly cast or ensure the session object is compatible with `pymongo.ClientSession` which Beanie expects internally, or check if an updated Beanie version resolves the type mismatch.","cause":"This type error occurs due to incompatibility between `motor` client session types (e.g., `AsyncIOMotorClientSession` or `AgnosticClientSession`) and the `ClientSession` type expected by Beanie's document methods, especially after `motor` updates that introduced stricter type hints.","error":"TypeError: 'AgnosticClientSession' cannot be assigned to 'ClientSession' in function 'find_one'"},{"fix":"Pass `response_type` only once as a keyword argument to the `update()` method, typically `response_type=UpdateResponse.NEW_DOCUMENT` or `response_type=UpdateResponse.UPDATE_RESULT`, according to the current Beanie documentation.","cause":"This error indicates that the `update()` method is being called with `response_type` both as a positional argument and a keyword argument, or due to changes in the method signature in `beanie` v2.x regarding how `response_type` should be passed.","error":"TypeError: beanie.odm.queries.find.FindOne.update() got multiple values for keyword argument 'response_type'"},{"fix":"While this is often an internal warning from Beanie itself that may be addressed in future library updates, if you are directly accessing `model_fields` in your custom code, change `instance.model_fields` to `YourModelClass.model_fields`. Ensure your Beanie version is compatible with Pydantic v2.","cause":"This is a Pydantic v2 deprecation warning (PydanticDeprecatedSince211) indicating that direct access to `model_fields` on a Pydantic model instance is deprecated in favor of accessing it via the model class (e.g., `YourModel.model_fields`).","error":"Pydantic 'model_fields' attribute on the instance is deprecated"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.28,"mem_mb":11.2,"disk_size":"37.7M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.2,"mem_mb":11.2,"disk_size":"39M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.45,"mem_mb":13.1,"disk_size":"42.1M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.37,"mem_mb":13.1,"disk_size":"44M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.61,"mem_mb":13.1,"disk_size":"33.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.56,"mem_mb":13.1,"disk_size":"36M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.6,"mem_mb":13.5,"disk_size":"33.1M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.55,"mem_mb":13.5,"disk_size":"36M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.25,"mem_mb":11,"disk_size":"37.0M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":11,"disk_size":"37M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}