xpipe-io/xpipe · error · IllegalArgumentException

Mixed source file systems

Error message

Mixed source file systems

What it means

Thrown by handleSingleAcrossFileSystems when files selected for a single transfer operation do not all originate from the same file system. The cross-file-system transfer path assumes one source FS and creates a transfer-optimized view for it, so mixed sources are rejected with an IllegalArgumentException.

Source

Thrown at app/src/main/java/io/xpipe/app/browser/file/BrowserFileTransferOperation.java:320

            var exists = source.getFileSystem().fileExists(source.getPath());
            if (!exists) {
                updateProgress(BrowserTransferProgress.finished(source.getName(), 0));
                return;
            }

            flatFiles.put(source, FilePath.of(source.getPath().getFileName()));
            // If we don't have a size, it doesn't matter that much as the total size is only for display
            totalSize.addAndGet(source.getFileSizeLong().orElse(0));
        } else {
            // Unsupported type, e.g. a socket
            updateProgress(BrowserTransferProgress.finished(source.getName(), 0));
            return;
        }

        var originalSourceFs = flatFiles.keySet().iterator().next().getFileSystem();
        if (!flatFiles.keySet().stream()
                .allMatch(fileEntry -> fileEntry.getFileSystem().equals(originalSourceFs))) {
            throw new IllegalArgumentException("Mixed source file systems");
        }

        var optimizedSourceFs = originalSourceFs.createTransferOptimizedFileSystem();
        var targetFs = target.getFileSystem().createTransferOptimizedFileSystem();

        try {
            AtomicLong transferred = new AtomicLong();
            for (var e : flatFiles.entrySet()) {
                if (cancelled()) {
                    return;
                }

                var sourceFile = e.getKey();
                var fixedRelPath = targetFs.makeFileSystemCompatible(e.getValue());
                var targetFile = target.getPath().join(fixedRelPath.toString());
                if (sourceFile.getFileSystem().equals(targetFs)) {
                    throw new IllegalStateException();
                }

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Perform one transfer per source file system
  2. Group selections so all files come from a single connection before transferring
  3. Split the batch into separate operations per source system
  4. In code, verify all entries share the same getFileSystem() before invoking

Example fix

// before
transfer(target, List.of(localEntry, remoteEntry))
// after
transfer(target, List.of(localEntry));      // first pass
transfer(target, List.of(remoteEntry));     // second pass
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleSourceFs(files) {
  const fsSet = new Set(files.map(f => f.fileSystemId));
  if (fsSet.size > 1) throw new Error('Mixed source file systems: split the transfer');
}

Try / catch

try {
  op.execute(target, files);
} catch (e) {
  if (e instanceof RangeError || String(e.message).includes('Mixed source file systems')) {
    // group entries by file system and transfer per group
  }
}

Prevention

When it happens

Trigger: Selecting files from two different connections/file systems in the browser and performing one consolidated transfer (e.g. dragging items from two systems into one target).

Common situations: Multi-select across opened remote connections, dragging from a local browser tab plus a remote tab simultaneously, or scripted transfers that aggregated entries from several systems.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06). Data as JSON: /api/errors/5771a8753b1e23a1. Report an issue: GitHub.