eclipse-vertx/vert.x · error · FileSystemException

Failed to move ${from} to ${to}

Error message

Failed to move ${from} to ${to}

What it means

The blocking move action in FileSystemImpl wraps IOException from java.nio.file.Files.move into FileSystemException 'Failed to move <from> to <to>'. Vert.x throws it when fileSystem().move/moveBlocking cannot rename or relocate the file at the OS level. The cause distinguishes missing source, existing target, or cross-filesystem issues.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java:487

        return null;
      }
    };
  }

  private BlockingAction<Void> moveInternal(String from, String to, CopyOptions options) {
    Objects.requireNonNull(from);
    Objects.requireNonNull(to);
    Objects.requireNonNull(options);
    Set<CopyOption> copyOptionSet = toCopyOptionSet(options);
    CopyOption[] copyOptions = copyOptionSet.toArray(new CopyOption[0]);
    return new BlockingAction<Void>() {
      public Void perform() {
        try {
          Path source = resolveFile(from).toPath();
          Path target = resolveFile(to).toPath();
          Files.move(source, target, copyOptions);
        } catch (IOException e) {
          throw new FileSystemException(getFileMoveErrorMessage(from, to), e);
        }
        return null;
      }
    };
  }

  private BlockingAction<Void> truncateInternal(String p, long len) {
    Objects.requireNonNull(p);
    return new BlockingAction<Void>() {
      public Void perform() {
        try {
          String path = resolveFile(p).getAbsolutePath();
          if (len < 0) {
            throw new FileSystemException("Cannot truncate file to size < 0");
          }
          if (!Files.exists(Paths.get(path))) {
            throw new FileSystemException("Cannot truncate file " + path + ". Does not exist");
          }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Check cause: NoSuchFileException -> verify source path; FileAlreadyExistsException -> add REPLACE_EXISTING or delete target first.
  2. For cross-filesystem moves, don't combine with ATOMIC_MOVE (or fall back to copy+delete) since rename(2) fails across devices.
  3. Close all streams/handles reading the source before moving; on Windows ensure antivirus/indexers release the lock.
  4. Create the target parent directory before the move.

Example fix

// before
vertx.fileSystem().moveBlocking("/tmp/upload/f.bin", "/data/f.bin"); // cross-device
// after: copy then delete
vertx.fileSystem().copyBlocking("/tmp/upload/f.bin", "/data/f.bin");
vertx.fileSystem().deleteBlocking("/tmp/upload/f.bin");
Defensive patterns

Strategy: validation

Validate before calling

FileSystem fs = vertx.fileSystem();
if (!fs.existsBlocking(from)) throw new FileNotFoundException(from);
if (fs.existsBlocking(to) && !overwrite) throw new FileAlreadyExistsException(to);
Files.createDirectories(Paths.get(to).getParent());
if (Paths.get(from).toFile().getFreeSpace() == 0 ||
    !Paths.get(from).toFile().equalsSamePathIfAtomic) { /* same-volume check */ }
if (!Files.isWritable(Paths.get(from).getParent())) throw new AccessDeniedException(from);

Type guard

static boolean isRenameable(Path from, Path to, boolean overwrite) {
  try {
    boolean sameVolume = Files.getFileStore(from).equals(Files.getFileStore(to.getParent()));
    return Files.exists(from) && sameVolume && (overwrite || !Files.exists(to));
  } catch (IOException e) { return false; }
}

Try / catch

try {
  fs.moveBlocking(from, to);
} catch (FileSystemException e) {
  if (e.getCause() instanceof AtomicMoveNotSupportedException
      || e.getCause() instanceof FileSystemException) {
    fs.copyBlocking(from, to, StandardCopyOption.REPLACE_EXISTING);
    fs.deleteBlocking(from); // fallback: copy+delete across devices
  } else throw e;
}

Prevention

When it happens

Trigger: vertx.fileSystem().move(from, to) where the source does not exist, the target exists without REPLACE_EXISTING, the target is on a different filesystem without ATOMIC_MOVE compatibility, or the source file is locked/open by another process (notably Windows).

Common situations: Moving a log/upload file while it is still being written; rename across mount points (e.g. /tmp to /app on different devices); target filename collision; Windows file locks from scanners or other readers; ATOMIC_MOVE combined with cross-device rename.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/708247f658bff984. Report an issue: GitHub.