Skip to content

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

@MGAMZ

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions