GoogleContainerTools/jib · error · IOException

unable to move: %s to %s; such failures are often caused by

Error message

unable to move: %s to %s; such failures are often caused by interference from antivirus (https://github.com/GoogleContainerTools/jib/issues/3127#issuecomment-796838294), or rarely if the operation is not supported by the file system (for example: special non-local file system)

What it means

CacheStorageWriter.moveIfDoesNotExist() renames a fully written temp file into its final cache location. After retrying the rename 10 times with 15ms pauses (on FileSystemException), a persistent failure throws IOException with a detailed message noting that antivirus interference or unsupported (non-local) file systems are the usual causes. This is the first throw site, after the retry loop exhausts.

Source

Thrown at jib-core/src/main/java/com/google/cloud/tools/jib/cache/CacheStorageWriter.java:146

          () -> {
            if (Files.exists(destination)) {
              // If the file already exists, we skip renaming and use the existing file.
              // This happens, e.g., if a new layer happens to have the same content as a
              // previously-cached layer or the same layer is being cached concurrently.
              return true;
            }
            Files.move(source, destination);
            return Files.exists(destination);
          };
      // Some Windows users report java.nio.file.AccessDeniedException that we suspect is caused
      // by anti-virus programs, like Windows Defender, that open new files for scanning.
      // Retry the rename up to 10 times, with 15ms pause between each retry.
      if (!Retry.action(rename)
          .maximumRetries(10)
          .retryOnException(ex -> ex instanceof FileSystemException)
          .sleep(15, TimeUnit.MILLISECONDS)
          .run()) {
        throw new IOException(errorMessage);
      }

    } catch (IOException ex) {
      throw new IOException(errorMessage, ex);
    }
  }

  /**
   * Decompresses the file to obtain the diff ID.
   *
   * @param compressedFile the file containing the compressed contents
   * @return the digest of the decompressed file
   * @throws IOException if an I/O exception occurs
   */
  private static DescriptorDigest getDiffIdByDecompressingFile(Path compressedFile)
      throws IOException {
    try (InputStream in =
        new CompressorStreamFactory(true)

View on GitHub (pinned to fb949e2676)

Solutions

  1. Move the Jib cache to a local disk (set <cache>/jib.cacheDirectory to a local path)
  2. Add the cache directory to antivirus exclusions
  3. Close processes holding files in the cache and rebuild
  4. Re-run the build — transient AV locks often disappear on retry

Example fix

// before (cache on network share)
<configuration><cache>/mnt/nfs/jib-cache</cache></configuration>
// after
<configuration><cache>/home/user/.cache/google-cloud-tools-java/jib</cache></configuration>
Defensive patterns

Strategy: retry

Validate before calling

// Cache must be on a local filesystem supporting atomic rename
if (!Files.getFileStore(cacheDir).supportsFileAttributeView("basic")) {
  System.err.println("Jib cache should be on a local disk");
}

Try / catch

try {
  build();
} catch (IOException e) {
  if (e.getMessage().startsWith("unable to move")) {
    // antivirus or non-local FS; relocate cache and retry
    setCacheDirectory(Path.of(System.getProperty("user.home"), ".cache/jib"));
    build();
  } else throw e;
}

Prevention

When it happens

Trigger: Files.move/ATOMIC_MOVE from source to destination keeps failing (e.g. FileAccessRetriedException / FileSystemException) through all 10 retries — typically while writeCompressed, writeUncompressed, writeTarLayer, or the layer blob writers move a temp layer file.

Common situations: Antivirus (Windows Defender etc.) locking freshly written files during scan, cache directory on NFS/SMB/network drives lacking atomic rename, another process holding the destination file open.

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 GoogleContainerTools/jib@fb949e2676 (2026-09-06). Data as JSON: /api/errors/260113250f35a028. Report an issue: GitHub.