Skip to content

[Bug]: pynwb.validate can not check with NWBZarrIO #2131

Description

@MGAMZ

What happened?

The pynwb.validate is designed to operate on both NWBHDF5IO or NWBZarrIO. But I found the current implementation cannot work properly when checking a Zarr-compressed NWB file. It seems to _validate_single_file incorrectly invoked the API of NWBZarrIO.

The issue is similar to hdmf-dev/hdmf-zarr#293, which also reports a validation error when checking a zarr-compressed nwb file. But its traceback seems to be different.

Steps to Reproduce

Create a zarr-compressed NWB file.

from hdmf_zarr import NWBZarrIO
with NWBZarrIO(output_path, 'w') as io:
    io.write(nwbfile)

Make sure that the file can be read by NWBZarrIO

print(NWBZarrIO.can_read(output_path))

should print True


Then, validate it:

import pynwb
pynwb.validate(path=output_path)

There should be errors, which is further attached below.

Traceback

The traceback varies depending on the configuration of use_cached_namespaces.

use_cached_namespaces=True (Default)

KeyError                                  Traceback (most recent call last)
File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/spec/namespace.py:466, in NamespaceCatalog.__load_namespace(self, namespace, reader, resolve)
    465 try:
--> 466     inc_ns = self.get_namespace(s['namespace'])
    467 except KeyError as e:

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:578, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
    577 pargs = _check_args(args, kwargs)
--> 578 return func(args[0], **pargs)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/spec/namespace.py:317, in NamespaceCatalog.get_namespace(self, **kwargs)
    316 if ret is None:
--> 317     raise KeyError("'%s' not a namespace" % name)
    318 return ret

KeyError: "'core' not a namespace"

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
Cell In[9], line 3
      1 import pynwb
----> 3 pynwb.validate(path=output_path, use_cached_namespaces=True)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:582, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
    580 def func_call(*args, **kwargs):
    581     pargs = _check_args(args, kwargs)
--> 582     return func(**pargs)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/pynwb/validation.py:163, in validate(**kwargs)
    161         validation_errors +=  _validate_single_file(path=p, **kwargs)
    162 else:
--> 163     validation_errors = _validate_single_file(path=path, **kwargs)
    165 return validation_errors

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/pynwb/validation.py:181, in _validate_single_file(**kwargs)
      0 <Error retrieving source code with stack_data see ipython/ipython#13598>

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/pynwb/validation.py:70, in get_cached_namespaces_to_validate(path, driver, aws_region, io)
     68     from pynwb import _get_backend
     69     backend_io = _get_backend(path, method=driver)
---> 70     namespace_dependencies = backend_io.load_namespaces(namespace_catalog=catalog, 
     71                                                         path=path, 
     72                                                         driver=driver, 
     73                                                         aws_region=aws_region)
     75 # Determine which namespaces are the most specific (i.e. extensions) and validate against those
     76 candidate_namespaces = set(namespace_dependencies.keys())

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:578, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
    576 def func_call(*args, **kwargs):
    577     pargs = _check_args(args, kwargs)
--> 578     return func(args[0], **pargs)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf_zarr/backend.py:285, in ZarrIO.load_namespaces(cls, namespace_catalog, path, storage_options, namespaces)
    283 ns_group = ns_group[latest_version]
    284 reader = ZarrSpecReader(ns_group)
--> 285 namespace_catalog.load_namespaces("namespace", reader=reader)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:578, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
    576 def func_call(*args, **kwargs):
    577     pargs = _check_args(args, kwargs)
--> 578     return func(args[0], **pargs)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/spec/namespace.py:578, in NamespaceCatalog.load_namespaces(self, **kwargs)
    576     # now load specs into namespace
    577     for ns in to_load:
--> 578         ret[ns['name']] = self.__load_namespace(ns, r, resolve=resolve)
    579     self.__included_specs[ns_path_key] = ret
    581 # warn if there are any ignored namespaces

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/spec/namespace.py:468, in NamespaceCatalog.__load_namespace(self, namespace, reader, resolve)
    466     inc_ns = self.get_namespace(s['namespace'])
    467 except KeyError as e:
--> 468     raise ValueError("Could not load namespace '%s'" % s['namespace']) from e
    469 if types_to_load is None:
    470     types_to_load = inc_ns.get_registered_types()  # load all types in namespace

ValueError: Could not load namespace 'core'

use_cached_namespaces=False

TypeError                                 Traceback (most recent call last)
Cell In[10], line 3
      1 import pynwb
----> 3 pynwb.validate(path=output_path, use_cached_namespaces=False)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:582, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
    580 def func_call(*args, **kwargs):
    581     pargs = _check_args(args, kwargs)
--> 582     return func(**pargs)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/pynwb/validation.py:163, in validate(**kwargs)
    161         validation_errors +=  _validate_single_file(path=p, **kwargs)
    162 else:
--> 163     validation_errors = _validate_single_file(path=path, **kwargs)
    165 return validation_errors

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/pynwb/validation.py:202, in _validate_single_file(**kwargs)
    200     from pynwb import _get_backend
    201     backend_io = _get_backend(path, method=driver)
--> 202     io = backend_io(**io_kwargs)
    204 # check namespaces are accurate
    205 if namespace is not None:

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:577, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
    576 def func_call(*args, **kwargs):
--> 577     pargs = _check_args(args, kwargs)
    578     return func(args[0], **pargs)

File ~/miniforge3/envs/dbci/lib/python3.13/site-packages/hdmf/utils.py:570, in docval.<locals>.dec.<locals>._check_args(args, kwargs)
    568     if parse_err:
    569         msg = '%s: %s' % (func.__qualname__, ', '.join(parse_err))
--> 570         raise ExceptionType(msg)
    572 return parsed['args']

TypeError: NWBZarrIO.__init__: unrecognized argument: 'driver'

Operating System

Linux

Python Executable

Conda

Python Version

3.13

Package Versions

environment_for_issue.txt

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions