Skip to content

VRT XML write in write_vrt is not atomic #2965

@brendancol

Description

@brendancol

Describe the bug

The VRT XML write in write_vrt (xrspatial/geotiff/_vrt.py) is not atomic. The final .vrt file is opened and written in place:

xml = '\n'.join(lines) + '\n'
with open(vrt_path, 'w') as f:
    f.write(xml)

If the process crashes, the disk fills up, or the write is interrupted between open and the finished write, a truncated .vrt is left at the final path.

This bites hardest on the tiled path. _write_vrt_tiled (xrspatial/geotiff/_writers/eager.py) writes every tile into a staging directory, promotes that directory to its final name with an atomic os.replace, and only then writes the VRT index. The index is the last non-atomic step, so a partial index ends up pointing at a fully-promoted, complete tile set. A reader that picks up the half-written VRT sees a valid tile directory behind a malformed index.

The other local writers in the module already handle this. _write_bytes in _writer.py writes to a temp file in the same directory and then os.replaces it into place. The VRT index write skips that path and writes directly.

Expected behavior

The VRT XML write should be atomic: write to a temp file in the same directory as the destination, then os.replace it into the final path. An interrupted or failed write should never leave a partial .vrt behind. The temp file has to live on the same filesystem as the destination for the rename to stay atomic. The fix should reuse the existing _write_bytes helper instead of duplicating the temp-then-rename logic.

Additional context

  • Cited line: the open(vrt_path, 'w') write at the end of write_vrt in xrspatial/geotiff/_vrt.py.
  • Promotion-before-index ordering: the os.replace(staging_dir, tiles_dir) followed by write_vrt(...) sequence in xrspatial/geotiff/_writers/eager.py.
  • Existing atomic helper: _write_bytes in xrspatial/geotiff/_writer.py.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggeotiffGeoTIFF moduleseverity:mediumSweep finding: MEDIUMvrtVRT support contract

    Type

    No type
    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