Skip to content

Transient NetCDF: Not a valid ID aborts a variable; not reproducible #649

Description

@rhaegar325

In one 100-variable batch run, ocean.tauuo crashed while reading a source
file. The other 99 passed.

Key: ('open_dataset-tau_x-c94b7655...', 0, 0, 0)
  File "access_moppy/base.py", line 1927, in write_next
    destination[slices] = future.result()
  File "src/netCDF4/_netCDF4.pyx", line 1750, in _get_format
RuntimeError: NetCDF: Not a valid ID

file: .../PI-CNP-concentrations-full/output005/ocean/ocean-2d-tau_x-1mon-mean-y_0106.nc
run:  /scratch/tm70/yz9299/piControl_parallel_thorough_cc_check_2  (job 177365482)

The error is raised in nc_inq_format, i.e. after nc_open returned, so
the ncid was already invalid — a corrupted netCDF-C file-table entry, not a bad
file.

Not the data

  • The file reads fine standalone (valid HDF5, NETCDF4_CLASSIC, values OK).
  • ACL is byte-identical to the neighbouring tau_y file.
  • ocean.tauvo — same pipeline, same directory, adjacent file — passed in the
    same batch.
  • Re-running the identical job passes (job 177370214, exit 0).

Suspected cause

A race on concurrent netCDF-C calls inside one worker process.
_parallel_open_is_safe() already names this exact symptom, but its
one-thread-per-worker guard only covers the compute thread: nc_close also
runs from GC on the event-loop thread when _write_dask_slices releases
futures. Consistent with the timing — the failing block is block 0 of the 6th
file, after five files had been read and released.

Two lock defects that would allow it, both demonstrated:

  1. SerializableLock._locks is a WeakValueDictionary. On a worker the token
    comes from the client process and nothing holds it, so once the last strong
    reference dies the next deserialisation builds a new threading.Lock
    under the same token and mutual exclusion silently stops.
  2. CombinedLock.acquire(blocking=False) is all(acquire(l, False) for l in self.locks). On short-circuit, lock 0 stays held;
    CachingFileManager.__del__ sees False and skips its release(), so it
    leaks permanently. Upstream xarray bug (2026.1.0); shows up as a hang, not
    this crash, but it is the same code path.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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