jenkinsci/jenkins · error · IOException

remote file operation failed

Error message

remote file operation failed

What it means

Thrown by FilePath.actAsync when wrapping the FileCallable and dispatching it over the channel fails with IOException. The fresh IOException preserves the caller's stack trace (remote exceptions lose the calling frame), with the original as cause. This wraps channel-level failures, not the inner callable's business exceptions.

Source

Thrown at core/src/main/java/hudson/FilePath.java:1300

        protected void after() {}
    }


    /**
     * Executes some program on the machine that this {@link FilePath} exists,
     * so that one can perform local file operations.
     */
    public <T> Future<T> actAsync(final FileCallable<T> callable) throws IOException, InterruptedException {
        try {
            DelegatingCallable<T, IOException> wrapper = new FileCallableWrapper<>(callable, this);
            for (FileCallableWrapperFactory factory : ExtensionList.lookup(FileCallableWrapperFactory.class)) {
                wrapper = factory.wrap(wrapper);
            }
            return (channel != null ? channel : localChannel)
                .callAsync(wrapper);
        } catch (IOException e) {
            // wrap it into a new IOException so that we get the caller's stack trace as well.
            throw new IOException("remote file operation failed", e);
        }
    }

    /**
     * Executes some program on the machine that this {@link FilePath} exists,
     * so that one can perform local file operations.
     */
    public <V, E extends Throwable> V act(Callable<V, E> callable) throws IOException, InterruptedException, E {
        if (channel != null) {
            // run this on a remote system
            return channel.call(callable);
        } else {
            // the file is on the local machine
            return callable.call();
        }
    }

    /**

View on GitHub (pinned to 2e228ff40b)

Solutions

  1. Ensure the agent is online and the channel is healthy before the call.
  2. Make the FileCallable and all its fields Serializable (use MasterToSlaveFileCallable).
  3. Inspect the cause for NotSerializableException and annotate/strip offending fields.
  4. Check FileCallableWrapperFactory extensions for failures.

Example fix

// before
fp.actAsync(in -> doWork(in)); // lambda may not be serializable
// after
fp.actAsync(new MasterToSlaveFileCallable<Result>() {
    private static final long serialVersionUID = 1L;
    public Result invoke(File f, VirtualChannel ch) { return doWork(f); }
});
Defensive patterns

Strategy: validation

Validate before calling

if (callable instanceof Serializable && channel != null && channel.isClosingOrClosed()) {
    // channel unhealthy — defer or fail fast before actAsync
}

Type guard

static boolean isRemotable(Object c) { return c instanceof Serializable; }

Try / catch

try {
    Future<T> f = fp.actAsync(callable);
} catch (IOException e) {
    // 'remote file operation failed' — check cause for channel/serialization issues
    if (e.getCause() instanceof NotSerializableException) { /* make callable serializable */ }
}

Prevention

When it happens

Trigger: Remoting channel is closed/disconnected; callable or its arguments are not serializable; FileCallableWrapperFactory wrapping throws; channel.callAsync raises IOException before dispatch.

Common situations: Agent went offline mid-operation; passing a non-Serializable lambda/closure to actAsync; channel degraded after a restart; custom FileCallableWrapperFactory throws.

Related errors


AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14). Data as JSON: /api/errors/034cb70229699a2e. Report an issue: GitHub.