astrid-runtime/astrid · error

destination.as_str()

Error message

destination.as_str()

What it means

rename_region rejects the operation with io::ErrorKind::AlreadyExists and the destination name when a region with that name already exists in the volume. Renames must produce a fresh name; the library refuses to silently overwrite an existing region (use replace_region for overwrite semantics).

Solutions

  1. Use replace_region instead when overwrite of an existing destination is intended.
  2. Delete the existing destination with remove_region before renaming, if the old contents are disposable.
  3. Generate a unique destination name (counter/uuid suffix) when creating new generations.
  4. Catch io::ErrorKind::AlreadyExists and branch to overwrite-or-skip logic at the call site.

Example fix

// before
volume.rename_region(&src, &dst)?; // AlreadyExists if dst exists
// after
if volume.region_exists(&dst) {
    volume.replace_region(&src, &dst)?;
} else {
    volume.rename_region(&src, &dst)?;
}
Defensive patterns

Strategy: validation

Validate before calling

if region_exists(&volume, &dst) {
    volume.replace_region(&src, &dst)?; // or remove dst first
} else {
    volume.rename_region(&src, &dst)?;
}

Type guard

fn rename_target_free(dst: &VolumeRegion, existing: &[String]) -> bool {
    !existing.iter().any(|r| r == dst.as_str())
}

Try / catch

if let Err(e) = volume.rename_region(&src, &dst) {
    if e.kind() == io::ErrorKind::AlreadyExists {
        // choose: overwrite via replace_region, or skip as already-done
    } else {
        return Err(e);
    }
}

Prevention

When it happens

Trigger: Calling rename_region(source, destination) where state.regions already contains destination: renaming onto a region created earlier, renaming to the region's own current name, or a leftover destination region from a prior run persisted in the volume file.

Common situations: Retry logic re-attempting a rename that already succeeded; installing a new generation over an old region name without deleting the old one first; generated destination names colliding (e.g. same timestamp); user expecting POSIX rename() overwrite semantics.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/9b957420cd9f79fc. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage/src/volume/hosted/mod.rs:335

        truncate_extents(&mut region_state.extents, length);
        region_state.length = length;
        Ok(())
    }

    fn remove_region(&self, region: &VolumeRegion) -> io::Result<()> {
        let mut state = self.state.lock();
        if !state.regions.contains_key(region) {
            return Err(io::Error::new(io::ErrorKind::NotFound, region.as_str()));
        }
        Self::append(&mut state, Operation::Remove, region, 0, &[])?;
        state.regions.remove(region);
        Ok(())
    }

    fn rename_region(&self, source: &VolumeRegion, destination: &VolumeRegion) -> io::Result<()> {
        let mut state = self.state.lock();
        if state.regions.contains_key(destination) {
            return Err(io::Error::new(
                io::ErrorKind::AlreadyExists,
                destination.as_str(),
            ));
        }
        if !state.regions.contains_key(source) {
            return Err(io::Error::new(io::ErrorKind::NotFound, source.as_str()));
        }
        Self::append(
            &mut state,
            Operation::Rename,
            source,
            0,
            destination.as_str().as_bytes(),
        )?;
        let source_state = state
            .regions
            .remove(source)
            .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, source.as_str()))?;

View on GitHub (pinned to affd8760f4)