Install & Compatibility
Where this runs
tested against v2026.5.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.960 runs
build_error
glibcpy 3.10–3.960 runs
installs and imports cleanly · install 38.5s · import 3.861s · 958MB
955MB installed
● package 955MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
processor
✓ from coffea import processor
Main module for defining analysis processors and runners.
ak
✓ import awkward as ak
Standard alias for Awkward Array, fundamental for columnar data structures.
hist
✓ import hist
Used for histogramming capabilities, often with dask-histogram.
This quickstart demonstrates how to define a simple `coffea` processor to perform a basic analysis task (selecting dimuons and histogramming their invariant mass). It uses `coffea.processor.ProcessorABC` and runs with the `IterativeExecutor` for local execution. Note that for a truly runnable example without ROOT files, a dummy `events` object is constructed, and actual file loading is omitted. In a real application, `NanoEventsFactory` would load data from ROOT files.
import awkward as ak
import hist
from coffea import processor
from coffea.nanoevents import NanoEventsFactory, BaseSchema
# Define a simple processor
class MyProcessor(processor.ProcessorABC):
def process(self, events):
# For demonstration, assume 'events' has a 'Muon' collection
# In a real scenario, events would be loaded from a file using NanoEventsFactory
if 'Muon' not in events.fields:
# Create dummy muons if not present, for runnable example
dummy_muons = ak.zip({
"pt": ak.Array([ [10, 20], [30] ]),
"eta": ak.Array([ [0.5, 1.2], [-0.8] ]),
"charge": ak.Array([ [1, -1], [1] ])
}, depth_limit=1)
events = ak.with_field(events, dummy_muons, "Muon")
muons = events.Muon[events.Muon.pt > 15]
# Select opposite-sign dimuons
dimuons = ak.combinations(muons, 2, fields=["lead", "trail"])
dimuons = dimuons[dimuons.lead.charge != dimuons.trail.charge]
# Calculate invariant mass (simplified for example)
# In a real analysis, vector-like operations would be used
if len(dimuons) > 0:
# Dummy mass calculation for illustration
mass = ak.flatten(dimuons.lead.pt + dimuons.trail.pt)
else:
mass = ak.Array([])
# Create a histogram and fill it
h_mass = hist.Hist.new.Reg(50, 0, 100, name="mass", label="Dimuon Mass [GeV]").Double()
h_mass.fill(mass=mass)
return {"mymass_histogram": h_mass, "nevents": len(events)}
def postprocess(self, accumulator):
return accumulator
# Example usage with a local executor
fileset = {"dataset_A": ["dummy_file.root"]}
# Create a dummy events object for local testing without actual file I/O
events_data = {"event_id": ak.Array([1, 2, 3])}
dummy_nanoevents = NanoEventsFactory.from_dict(events_data, schemaclass=BaseSchema).events()
# Instantiate the processor
my_processor_instance = MyProcessor()
# Run the processor with a local executor
# In a real scenario, you'd load actual ROOT files
output = processor.Runner(
executor=processor.IterativeExecutor(status=False),
schema=BaseSchema,
xrootdtimeout=0 # dummy, for local execution
)(fileset, "Events", processor_instance=my_processor_instance)
print(output["mymass_histogram"])
Debug
Known issues
breakingPython 3.9 support was dropped in `coffea` version 2025.12.0. Users on older Python versions will need to upgrade their environment to Python 3.10 or newer to use recent `coffea` releases.fixUpgrade your Python environment to 3.10 or later (`conda install python=3.10` or similar).
affects: >=2025.12.0
breakingMajor API changes and mandatory `dask-awkward` dependency occurred when migrating from `coffea 0.7.x` to the calendar-versioned releases (`202X.Y.Z`). This transition involved fundamental shifts due to `awkward-array` v1 to v2 migration, making `dask-awkward` and `dask-histogram` mandatory for delayed computation. Old code might require significant updates to adapt to the new pattern, particularly regarding explicit `.compute()` calls.fixConsult the `coffea` migration guides for detailed instructions. Ensure `dask-awkward` and `dask-histogram` are installed. Refactor analysis logic to leverage lazy evaluation and use `.compute()` only at the very end of array/histogram construction.
affects: All versions >=2023.0.0 (approx.)
gotchaProcessorABC instances are expected to be fully serializable for distributed execution. Avoid tracking mutable state within a `ProcessorABC` instance, as it's treated as a stateless bundle of methods. Issues can arise with non-picklable objects or shared state that isn't properly handled during serialization/deserialization.fixEnsure all components of your `ProcessorABC` are picklable. For shared data or configurations, pass them into the `__init__` method and ensure they are read-only or managed externally. Test serialization with `coffea.util.save(my_processor_instance, 'test.coffea')`.
affects: All versions
gotchaPremature calls to `.compute()` on `dask-awkward` arrays or `dask-histogram` objects can severely degrade performance in `coffea` analyses. Explicit `.compute()` calls force immediate evaluation, breaking the efficient Dask task graph designed for lazy, distributed processing.fixStructure your analysis to delay computation as much as possible. Only call `.compute()` when you need the final, fully-evaluated result (e.g., for plotting or saving to a concrete array/histogram object). `coffea`'s runners handle `.compute()` implicitly at the end of the processing chain.
affects: All versions >=2023.0.0
gotchaThe `coffea` project transitioned from semantic versioning (e.g., `0.7.x`) to calendar versioning (e.g., `202X.Y.Z`). There is an active `0.7.x` backports branch. This dual-versioning scheme can lead to confusion and API incompatibilities if users are not careful to install and develop against the intended version series.fixAlways explicitly specify the desired version during installation (`pip install 'coffea>=2026.0.0,<2027.0.0'` for calendar versions, or `pip install 'coffea~=0.7.0'` for the backports). Be mindful of which documentation version corresponds to your installed library.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'awkward.array'
This error typically occurs in older `coffea` versions (e.g., 0.6.46) due to a renaming of internal modules within the `awkward-array` library, a key dependency for `coffea`.
fixUpgrade `coffea` to a newer version (e.g., `pip install --upgrade coffea` or `conda update coffea`) which has adapted to the `awkward-array` changes.
ModuleNotFound errors when attempting to run my processor. Ensure that you have installed your package onto the workers as well.
When running `coffea` processors with distributed executors (like Dask), required Python packages or analysis-specific files are often installed only on the client machine and not propagated to the Dask workers, leading to `ModuleNotFoundError` or `FileNotFoundError` on the workers.
fixEnsure all necessary packages and custom files are available on the Dask workers. This can be done by installing them into the worker's environment or by using Dask's `client.upload_file()` or `job_extra` configuration (e.g., `transfer_input_files` for `CoffeaCasaCluster`).
AttributeError: no field named 'compute'
In recent `coffea` versions (e.g., v2025.7.0 and later), the default behavior of `NanoEventsFactory.from_root()` changed to use virtual arrays (lazy loading without Dask-Awkward by default), meaning `.compute()` is no longer directly applicable to materialize results.
fixInstead of `.compute()`, use `awkward.materialize()` (often imported as `ak.materialize()`) to force the evaluation and loading of the array data. Alternatively, configure `NanoEventsFactory` to explicitly use `dask-awkward` if distributed computation is desired.
cannot pickle 'property' object
This error occurs when `coffea` attempts to serialize (pickle) an object, often a processor, that contains Python `property` objects which are not directly pickleable across processes, particularly with Dask or `concurrent.futures` executors.
fixEnsure that any objects passed to the `coffea` executor (especially processors) are fully pickleable. This often means avoiding complex closures, lambda functions, or certain class attributes that are `property` objects, or making sure they are defined at the top level of a module. For processors, ensure all internal state is managed in a pickle-friendly way.
Upgrade
Version history
2026.5.0latest on PyPI · released May 25, 2026
Audit
Dependencies
pythonrequiredRequired Python version.
numpyrequiredCore array manipulation.
uprootrequiredInteracting with ROOT files.
awkward-arrayrequiredManipulating complex-structured columnar data (jagged arrays).
numbarequiredJust-in-time compilation of Python functions.
scipyrequiredStatistical functions.
matplotlibrequiredPlotting backend.
daskoptionalDistributed executor for scaling analyses.
parsloptionalDistributed executor for scaling analyses.
taskvineoptionalDistributed executor for scaling analyses.