tursodatabase/turso · error

punch_hole is not supported for the given IO implementation

Error message

punch_hole is not supported for the given IO implementation

What it means

punch_hole() is an optional IO trait method whose default implementation panics. It de-allocates contiguous file regions (holes) and is used by the sync engine in partial-sync mode only; core database code never calls it. Invoking it on an IO backend that did not override it crashes.

Source

Thrown at core/io/mod.rs:215

        Ok(c)
    }
    fn size(&self) -> Result<u64>;
    fn truncate(&self, len: u64, c: Completion) -> Result<Completion>;

    /// Optional method implemented by the IO which supports "partial" files (e.g. file with "holes")
    /// This method is used in sync engine only for now (in partial sync mode) and never used in the core database code
    ///
    /// The hole is the contiguous file region which is not allocated by the file-system
    /// If there is a single byte which is allocated within a given range - method must return false in this case
    // todo: need to add custom completion type?
    fn has_hole(&self, _pos: usize, _len: usize) -> Result<bool> {
        panic!("has_hole is not supported for the given IO implementation")
    }
    /// Optional method implemented by the IO which supports "partial" files (e.g. file with "holes")
    /// This method is used in sync engine only for now (in partial sync mode) and never used in the core database code
    // todo: need to add custom completion type?
    fn punch_hole(&self, _pos: usize, _len: usize) -> Result<()> {
        panic!("punch_hole is not supported for the given IO implementation")
    }

    fn shared_wal_lock_byte(
        &self,
        _offset: u64,
        _exclusive: bool,
        _kind: SharedWalLockKind,
    ) -> Result<()> {
        Err(crate::LimboError::InternalError(
            "shared WAL coordination byte locking is not supported for this file".into(),
        ))
    }

    fn shared_wal_try_lock_byte(
        &self,
        _offset: u64,
        _exclusive: bool,
        _kind: SharedWalLockKind,

View on GitHub (pinned to 6c72522679)

Solutions

  1. Run partial sync on the file-backed platform IO over a filesystem supporting hole punching (ext4, XFS, btrfs)
  2. Disable partial-sync mode and use full sync
  3. For custom IO: implement punch_hole()/has_hole() or maintain an allocation map

Example fix

// before
// partial sync punches holes through an IO that cannot -> panics
engine.enable_partial_sync(memory_io);

// after
// file-backed IO on ext4/xfs implements punch_hole via fallocate
engine.enable_partial_sync(platform_file_io);
Defensive patterns

Strategy: fallback

Validate before calling

// same capability gate as has_hole: only punch holes through file-backed IO
if !io_supports_holes(&io) {
    engine.use_full_sync(); // avoid punch_hole entirely
} else {
    engine.enable_partial_sync(io);
}

Prevention

When it happens

Trigger: Partial sync running punch_hole on an IO without sparse-file support: in-memory IO, custom test backends, or filesystems where hole punching is unavailable (NFS varies, older tmpfs, some Windows configs).

Common situations: Testing the sync engine against memory IO; deploying partial sync onto a filesystem without fallocate/FALLOC_FL_PUNCH_HOLE.

Related errors


AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20). Data as JSON: /api/errors/b8b6e833b643d01e. Report an issue: GitHub.