Kùzu, the embedded graph database, was archived in October 2025. LadybugDB carries it on (pip install ladybug), but the old kuzu package still gets about 90,000 downloads a week, and nothing on its PyPI page says where development went.
I benchmark coding agents on adopting and upgrading libraries, so I gave three of them (Claude Code, Codex, Gemini) a small project and asked twice each. Told to "use Kùzu", all 6 runs installed the archived package. Given a project halfway through the move, with one module still on Kùzu, all 6 hit the same error the moment both libraries were loaded:
RuntimeError: Could not find lbug C API shared library. ... failed to load: generic_type: type "Database" is already registered!
The first sentence sends you to download a shared library. The real cause is at the end: kuzu and ladybug register the same internal types, so they can't live in one Python process. Five runs moved the Kùzu call into a subprocess. The sixth popped pybind11's registry entries with ctypes so both would load. It works, and nobody should ship it.
Then I did the migration by hand to find the clean way. Two surprises. First, the database file: LadybugDB's notes say old files are "generally compatible", but ladybug 0.22.3 refused a file written by kuzu 0.11.3 ("not a valid Lbug database file"). EXPORT DATABASE with kuzu and IMPORT DATABASE with ladybug moved everything, dates, lists and relationship properties included. Second, the code: the Python API is the same, so finishing the half-done migration took three lines. "One module at a time" was the wrong plan here; the only reason to keep kuzu around is a dependency that still requires it, and then it gets its own process.
Check if this applies to you
Applies if: a Python project (any folder with .py files or a requirements/pyproject file). Read-only steps:
grep -rniE '^\s*(import kuzu|from kuzu)' --include='*.py' .grep -niE '^kuzu' requirements*.txt pyproject.toml setup.cfg 2>/dev/null- In the project's virtual environment:
python -m pip show kuzu(note theRequired-by:line). find . -name '*.kuzu' -not -path './.venv/*'
Has the problem: step 1, 2 or 3 finds kuzu (the project depends on the archived package, directly or through a dependency). Doesn't have it: none of the steps finds kuzu.
Reproduce this
Prerequisites: a Python project that uses kuzu (tested with kuzu 0.11.3, ladybug 0.22.3, Python 3.13 on macOS arm64). A copy or backup of every Kùzu database file before you start.
Your agent will need from you: where the project's Kùzu databases live (paths), and whether they hold data to keep or are rebuilt from source files.
Steps:
- Inventory. List every file that imports
kuzu, every requirements entry, and every Kùzu database path the code opens. Runpython -m pip show kuzuin the project's environment: ifRequired-by:names a package (for examplekuzu-memory, orgraphiti-coreinstalled with thekuzuextra), that package still needskuzuand step 7 applies. - Export each database that holds data to keep, with
kuzu, in its own process, before installing anything:python -c "import kuzu; kuzu.Connection(kuzu.Database('PATH', read_only=True)).execute(\"EXPORT DATABASE 'PATH_export'\")"This writesschema.cypher,copy.cypherand one Parquet file per table. Do not try to open the old file with ladybug: 0.22.3 rejects 0.11.3 files. - Install
ladybug(python -m pip install ladybug) and replacekuzuwithladybugin requirements. Keepkuzuonly if step 1 found a dependency that requires it. - Change the code:
import kuzubecomesimport ladybug(orimport ladybug as lb), andkuzu.Database,kuzu.Connectionbecomeladybug.Database,ladybug.Connection. Queries, parameters and result methods (execute,has_next,get_next,get_as_df,rows_as_dict) stay the same. Point the code at a new database path (for example.lbuginstead of.kuzu) so the old file stays as a backup. - Import each export into a new database, with
ladybug, in its own process:python -c "import ladybug; ladybug.Connection(ladybug.Database('NEW_PATH')).execute(\"IMPORT DATABASE 'PATH_export'\")"Databases rebuilt from source files (CSV loaders, fixtures) need no export: just run the loader on ladybug. - Migrate every module in one change. The API is the same, so there is no reason to leave one module on Kùzu, and
kuzuandladybugcannot be imported in the same Python process (in either order). - Only if a dependency still requires
kuzu: run the code that uses that dependency in its own process (a small worker script started withsubprocess.run([sys.executable, "worker.py", ...])that prints JSON), and never import it in the process that importsladybug. Do not follow the error's hint to setLBUG_C_API_LIB_PATHor download a shared library, and do not patch pybind11's registry: neither fixes the clash. - When nothing requires it any more:
python -m pip uninstall -y kuzu.
Verify:
- For each migrated database, the row count of every node and relationship table is the same in the old database (counted with
kuzu) and the new one (counted withladybug), in separate processes:MATCH (n:Table) RETURN count(n)andMATCH ()-[r:Rel]->() RETURN count(r). - The project's own tests or entry point give the same results as before the migration.
python -c "import sys; import <your app's main module>; print('kuzu' in sys.modules)"printsFalse.grep -rniE '^\s*(import kuzu|from kuzu)' --include='*.py' .finds nothing outside a step 7 worker.