# Buggy code
def _detect_output_fields(self):
    """Populates ``self.field_list`` with native fields (mesh and particle) on disk.

    Each entry is a tuple of two strings. The first element is the on-disk fluid type or particle type.
    The second element is the name of the field in yt. This string is later used for accessing the data.
    Convention suggests that the on-disk fluid type should be "openPMD",
    the on-disk particle type (for a single species of particles) is "io"
    or (for multiple species of particles) the particle name on-disk.
    """
    f = self.dataset._handle
    bp = self.dataset.base_path
    mp = self.dataset.meshes_path
    pp = self.dataset.particles_path

    mesh_fields = []
    try:
        for field in f[bp + mp].keys():
            try:
                for axis in f[bp + mp + field].keys():
                    mesh_fields.append(field.replace("_", "-") + "_" + axis)
            except AttributeError:
                # This is a h5.Dataset (i.e. no axes)
                mesh_fields.append(field.replace("_", "-"))
    except KeyError:
        # There are no mesh fields
        pass
    self.field_list = [("openPMD", str(field)) for field in mesh_fields]

    particle_fields = []
    try:
        for species in f[bp + pp].keys():
            for record in f[bp + pp + species].keys():
                if is_const_component(f[bp + pp + species + "/" + record]):
                    # Record itself (e.g. particle_mass) is constant
                    particle_fields.append(
                        species.replace("_", "-") + "_" + record.replace("_", "-")
                    )
                elif "particlePatches" not in record:
                    try:
                        # Create a field for every axis (x,y,z) of every property (position)
                        # of every species (electrons)
                        axes = list(f[bp + pp + species + "/" + record].keys())
                        if str(record) == "position":
                            record = "positionCoarse"
                        for axis in axes:
                            particle_fields.append(
                                species.replace("_", "-")
                                + "_"
                                + record.replace("_", "-")
                                + "_"
                                + axis
                            )
                    except AttributeError:
                        # Record is a dataset, does not have axes (e.g. weighting)
                        particle_fields.append(
                            species.replace("_", "-") + "_" + record.replace("_", "-")
                        )
                        pass
                else:
                    pass
        if len(list(f[bp + pp].keys())) > 1:
            # There is more than one particle species, use the specific names as field types
            self.field_list.extend(
                [
                    (
                        str(field).split("_")[0],
                        ("particle_" + "_".join(str(field).split("_")[1:])),
                    )
                    for field in particle_fields
                ]
            )
        else:
            # Only one particle species, fall back to "io"
            self.field_list.extend(
                [
                    ("io", ("particle_" + "_".join(str(field).split("_")[1:])))
                    for field in particle_fields
                ]
            )
    except KeyError:
        # There are no particle fields
        pass


# Traceback (KeyError)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-6-606762cc9ee1> in <module>()
----> 1 yt.load('./example-ptcl/hdf5/data00000400.h5')

~/miniconda3/lib/python3.6/site-packages/yt/convenience.py in load(*args, **kwargs)
84     candidates = find_lowest_subclasses(candidates)
85     if len(candidates) == 1:
---> 86         return candidates[0](*args, **kwargs)
87     if len(candidates) == 0:
88         if ytcfg.get("yt", "enzo_db") != '' \

~/miniconda3/lib/python3.6/site-packages/yt/frontends/open_pmd/data_structures.py in __init__(self, filename, dataset_type, storage_filename, units_override, unit_system, **kwargs)
385         self.storage_filename = storage_filename
386         self.fluid_types += ("openPMD",)
--> 387         particles = tuple(str(c) for c in self._handle[self.base_path + self.particles_path].keys())
388         if len(particles) > 1:
389             # Only use on-disk particle names if there is more than one species

~/miniconda3/lib/python3.6/site-packages/yt/utilities/file_handler.py in __getitem__(self, key)
43
44     def __getitem__(self, key):
---> 45         return self.handle[key]
46
47     def __contains__(self, item):

h5py/_objects.pyx in h5py._objects.with_phil.wrapper (/Users/ilan/minonda/conda-bld/h5py_1496887972496/work/h5py/_objects.c:2846)()

h5py/_objects.pyx in h5py._objects.with_phil.wrapper (/Users/ilan/minonda/conda-bld/h5py_1496887972496/work/h5py/_objects.c:2804)()

~/miniconda3/lib/python3.6/site-packages/h5py/_hl/group.py in __getitem__(self, name)
167                 raise ValueError("Invalid HDF5 object reference")
168         else:
--> 169             oid = h5o.open(self.id, self._e(name), lapl=self._lapl)
170
171         otype = h5i.get_type(oid)

h5py/_objects.pyx in h5py._objects.with_phil.wrapper (/Users/ilan/minonda/conda-bld/h5py_1496887972496/work/h5py/_objects.c:2846)()

h5py/_objects.pyx in h5py._objects.with_phil.wrapper (/Users/ilan/minonda/conda-bld/h5py_1496887972496/work/h5py/_objects.c:2804)()

h5py/h5o.pyx in h5py.h5o.open (/Users/ilan/minonda/conda-bld/h5py_1496887972496/work/h5py/h5o.c:3740)()

KeyError: "Unable to open object (Object 'particles' doesn't exist)"

# Fixed code
def _detect_output_fields(self):
    """Populates ``self.field_list`` with native fields (mesh and particle) on disk.

    Each entry is a tuple of two strings. The first element is the on-disk fluid type or particle type.
    The second element is the name of the field in yt. This string is later used for accessing the data.
    Convention suggests that the on-disk fluid type should be "openPMD",
    the on-disk particle type (for a single species of particles) is "io"
    or (for multiple species of particles) the particle name on-disk.
    """
    f = self.dataset._handle
    bp = self.dataset.base_path
    mp = self.dataset.meshes_path
    pp = self.dataset.particles_path

    mesh_fields = []
    try:
        meshes = f[bp + mp]
        for mname in meshes.keys():
            try:
                mesh = meshes[mname]
                for axis in mesh.keys():
                    mesh_fields.append(mname.replace("_", "-") + "_" + axis)
            except AttributeError:
                # This is a h5.Dataset (i.e. no axes)
                mesh_fields.append(mname.replace("_", "-"))
    except KeyError:
        pass
    self.field_list = [("openPMD", str(field)) for field in mesh_fields]

    particle_fields = []
    try:
        particles = f[bp + pp]
        for pname in particles.keys():
            species = particles[pname]
            for recname in species.keys():
                record = species[recname]
                if is_const_component(record):
                    # Record itself (e.g. particle_mass) is constant
                    particle_fields.append(
                        pname.replace("_", "-") + "_" + recname.replace("_", "-")
                    )
                elif "particlePatches" not in recname:
                    try:
                        # Create a field for every axis (x,y,z) of every property (position)
                        # of every species (electrons)
                        axes = list(record.keys())
                        if str(recname) == "position":
                            recname = "positionCoarse"
                        for axis in axes:
                            particle_fields.append(
                                pname.replace("_", "-")
                                + "_"
                                + recname.replace("_", "-")
                                + "_"
                                + axis
                            )
                    except AttributeError:
                        # Record is a dataset, does not have axes (e.g. weighting)
                        particle_fields.append(
                            pname.replace("_", "-") + "_" + recname.replace("_", "-")
                        )
                        pass
                else:
                    pass
        if len(list(particles.keys())) > 1:
            # There is more than one particle species, use the specific names as field types
            self.field_list.extend(
                [
                    (
                        str(field).split("_")[0],
                        ("particle_" + "_".join(str(field).split("_")[1:])),
                    )
                    for field in particle_fields
                ]
            )
        else:
            # Only one particle species, fall back to "io"
            self.field_list.extend(
                [
                    ("io", ("particle_" + "_".join(str(field).split("_")[1:])))
                    for field in particle_fields
                ]
            )
    except KeyError:
        pass