render_shapes crashes with KeyError: None when table instance IDs don't match element
Description
When calling render_shapes("s", color="cat", table_name="t") where the table correctly annotates element "s" (region key matches) but none of the table's instance_id values overlap with the element's actual instance IDs, the call crashes with a bare KeyError: None from deep inside pandas. The user gets a 15+ frame traceback that terminates in element.loc[None, :] with no indication of what went wrong or how to fix it.
Root cause: join_spatialelement_table(..., how="inner") returns an empty result. The downstream code passes None as an index to element.loc, which pandas raises as KeyError: None.
Environment
spatialdata-plot: 0.3.4.dev (main, 5cfedc7)
spatialdata: 0.5.0
Python: 3.13
Minimal Reproducible Example
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import geopandas as gpd
import anndata as ad
import spatialdata as sd
from spatialdata.models import ShapesModel, TableModel
import spatialdata_plot
from shapely.geometry import Point
shapes = ShapesModel.parse(gpd.GeoDataFrame({
"geometry": [Point(5, 5), Point(15, 5), Point(25, 5)],
"radius": [2.0] * 3,
}))
obs = pd.DataFrame({
"instance_id": [99, 100, 101], # element has IDs 0, 1, 2 — no overlap
"region": pd.Categorical(["s"] * 3),
"cat": pd.Categorical(["A", "B", "C"]),
})
obs.index = obs.index.astype(str)
table = TableModel.parse(
ad.AnnData(X=np.zeros((3, 1)), obs=obs),
region=["s"], region_key="region", instance_key="instance_id",
)
sdata = sd.SpatialData(shapes={"s": shapes}, tables={"t": table})
fig, ax = plt.subplots()
sdata.pl.render_shapes("s", color="cat", table_name="t").pl.show(ax=ax)
Actual Output
Full traceback ends at element.loc[None, :] buried in spatialdata internals (_get_masked_element). No indication that the instance ID sets are disjoint.
Expected Output
Either:
- All shapes rendered in
na_color with a UserWarning: "No instance IDs in table 't' overlap with element 's'. Shapes will be rendered with na_color."
- Or a clear
ValueError: "No instance IDs overlap between table 't' (instance_key='instance_id') and element 's'. Check that the table's instance_id column matches the element's index."
Fix Sketch
In _render_shapes (and analogously _render_labels, _render_points), before calling join_spatialelement_table, check whether the intersection of table instance IDs and element instance IDs is empty. If so, warn and skip coloring (fall back to na_color) or raise a descriptive ValueError.
element_ids = set(element.index)
table_ids = set(table.obs[instance_key])
if element_ids.isdisjoint(table_ids):
raise ValueError(
f"No instance IDs overlap between table '{table_name}' "
f"(instance_key='{instance_key}') and element '{element_name}'. "
f"Check that the table's instance_id column matches the element's index."
)
Note: the root cause lives upstream in spatialdata._get_masked_element, but a guard in spatialdata-plot provides immediate user-facing relief without requiring a coordinated upstream fix.
Triage tier: Tier 2
render_shapescrashes withKeyError: Nonewhen table instance IDs don't match elementDescription
When calling
render_shapes("s", color="cat", table_name="t")where the table correctly annotates element"s"(region key matches) but none of the table'sinstance_idvalues overlap with the element's actual instance IDs, the call crashes with a bareKeyError: Nonefrom deep inside pandas. The user gets a 15+ frame traceback that terminates inelement.loc[None, :]with no indication of what went wrong or how to fix it.Root cause:
join_spatialelement_table(..., how="inner")returns an empty result. The downstream code passesNoneas an index toelement.loc, which pandas raises asKeyError: None.Environment
Minimal Reproducible Example
Actual Output
Full traceback ends at
element.loc[None, :]buried in spatialdata internals (_get_masked_element). No indication that the instance ID sets are disjoint.Expected Output
Either:
na_colorwith aUserWarning:"No instance IDs in table 't' overlap with element 's'. Shapes will be rendered with na_color."ValueError:"No instance IDs overlap between table 't' (instance_key='instance_id') and element 's'. Check that the table's instance_id column matches the element's index."Fix Sketch
In
_render_shapes(and analogously_render_labels,_render_points), before callingjoin_spatialelement_table, check whether the intersection of table instance IDs and element instance IDs is empty. If so, warn and skip coloring (fall back tona_color) or raise a descriptiveValueError.Note: the root cause lives upstream in
spatialdata._get_masked_element, but a guard inspatialdata-plotprovides immediate user-facing relief without requiring a coordinated upstream fix.Triage tier: Tier 2