Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

`ingest` fails with pynndescent 0.7

Open Beginner friendly
#4,450 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@eroell is already working on this.

Since Oct 28, 2026.

  • #4451 by @eroell — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
68/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
numpy, python

Research direction

Start in scanpy/tools/_ingest.py, especially Ingest._init_pynndescent, and trace how it passes NNDescent.n_search_trees to make_forest. Reproduce with the provided minimal script using pynndescent 0.7.0, then check that sc.tl.ingest succeeds and existing ingest tests still pass.

Written by the indexing model from the issue text.

Description

Triage 🩺
Please make sure these conditions are met
  • I have checked that this issue has not already been reported.
  • I have confirmed this bug exists on the latest version of scanpy.
  • (optional) I have confirmed this bug exists on the main branch of scanpy.
What happened?

pynndescent 0.7.0 deprecated NNDescent.n_search_trees (now None), and the make_forest workaround in Ingest._init_pynndescent passes it on. Works with pynndescent 0.6.0. Related: #4444

Minimal code sample
# /// script
# requires-python = ">=3.13"
# dependencies = [
#   "scanpy@git+https://github.com/scverse/scanpy.git@main",
# ]
# ///
#
# This script automatically imports the development branch of scanpy to check for issues

import anndata as ad
import numpy as np
import scanpy as sc

adata = ad.AnnData(np.random.default_rng(0).normal(size=(300, 20)).astype(np.float32))
adata_ref, adata_new = adata[:200].copy(), adata[200:].copy()
sc.pp.pca(adata_ref)
sc.pp.neighbors(adata_ref)
sc.tl.umap(adata_ref)
sc.tl.ingest(adata_new, adata_ref)
Error output
Traceback (most recent call last):
  File "issue_repro.py", line 19, in <module>
    sc.tl.ingest(adata_new, adata_ref)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File ".../site-packages/scanpy/tools/_ingest.py", line 139, in ingest
    ing = Ingest(adata_ref, neighbors_key)
  File ".../site-packages/scanpy/tools/_ingest.py", line 376, in __init__
    self._init_neighbors(adata, neighbors_key)
    ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File ".../site-packages/scanpy/tools/_ingest.py", line 323, in _init_neighbors
    self._init_pynndescent(
    ~~~~~~~~~~~~~~~~~~~~~~^
        neighbors["distances"], rng=self._get_rng(neighbors["params"])
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File ".../site-packages/scanpy/tools/_ingest.py", line 290, in _init_pynndescent
    self._nnd_idx._rp_forest = make_forest(
                               ~~~~~~~~~~~^
        self._nnd_idx._raw_data,
        ^^^^^^^^^^^^^^^^^^^^^^^^
    ...<6 lines>...
        self._nnd_idx._angular_trees,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File ".../site-packages/pynndescent/rp_trees.py", line 3020, in make_forest
    rng_states = random_state.randint(INT32_MIN, INT32_MAX, size=(n_trees, 3)).astype(
                 ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "numpy/random/mtrand.pyx", line 801, in numpy.random.mtrand.RandomState.randint
  File "numpy/random/_bounded_integers.pyx", line 1315, in numpy.random._bounded_integers._rand_int64
  File ".../site-packages/numpy/_core/fromnumeric.py", line 3442, in prod
    return _wrapreduction(a, np.multiply, 'prod', axis, dtype, out,
                          keepdims=keepdims, initial=initial, where=where)
  File ".../site-packages/numpy/_core/fromnumeric.py", line 83, in _wrapreduction
    return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
Versions

pynndescent 0.7.0, umap-learn 0.5.12 (not listed by print_versions)

scanpy	1.14.0.dev35+g6f523e64e
----	----
pandas	3.1.0
cloudpickle	3.1.2
python-dateutil	3.0.0
pydantic_core	2.50.1
llvmlite	0.50.0
scikit-learn	1.9.1
fast-array-utils	1.5.1
anndata	0.13.4
msgspec	0.22.0
narwhals	2.28.0
scipy	1.18.1
joblib	1.6.0
zarr	3.4.2
packaging	26.3
matplotlib	3.11.2
PyYAML	6.0.3
scverse-misc	0.1.7
cycler	0.12.1
numcodecs	0.17.1
annotated-types	0.8.0
pydantic-settings	2.16.1
charset-normalizer	3.5.2
typing-inspection	0.4.4
donfig	0.8.1.post1
pyparsing	3.3.3
pillow	13.0.0
python-dotenv	1.2.4
numba	0.68.1
typing_extensions	4.16.0
google-crc32c	1.9.0
fonttools	4.68.0
pydantic	2.14.1
natsort	8.4.0
h5py	3.16.0
session-info2	0.4.2
legacy-api-wrap	1.5
threadpoolctl	3.7.0
six	1.17.0
numpy	2.5.4
kiwisolver	1.5.1
----	----
Python	3.14.3 (main, Mar 10 2026, 18:18:50) [Clang 21.1.4 ]
OS	Linux-6.12.0-211.47.1.el10_2.x86_64-x86_64-with-glibc2.39
CPU	8/96 logical CPU cores
GPU	No GPU found
Updated	2026-10-28 08:57
Dominant language
Python
Stars
2.6k
Forks
808
Avg merge
1d 8h
Merged PRs (30d)
17

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from scverse/scanpy

All issues in scverse/scanpy

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.