influxdata/influxdb · error · ProcessingEngineError::PluginError

Failed to rename temp directory to target

Error message

Failed to rename temp directory to target

What it means

replace_plugin_directory() performs an atomic swap: new files go to a '.tmp' directory, the current one is moved to '.old', then async_fs::rename(tmp -> target) runs. If that final rename fails, the engine rolls back (restores '.old' to the target, deletes the temp dir) and returns the filesystem error with context 'Failed to rename temp directory to target'. The rollback means the previously installed plugin version is preserved.

Source

Thrown at influxdb3_processing_engine/src/lib.rs:1255

                    tokio::spawn(async move {
                        let _ = async_fs::remove_dir_all(temp_clone).await;
                    });
                    ProcessingEngineError::PluginError(PluginError::AnyhowError(e))
                })?;
        }

        let rename_result = async_fs::rename(&temp_path, &plugin_path).await;

        if let Err(e) = rename_result {
            // Rollback: restore old directory if it exists
            if old_path.exists() {
                let _ = async_fs::rename(&old_path, &plugin_path).await;
            }
            let _ = async_fs::remove_dir_all(&temp_path).await;

            return Err(ProcessingEngineError::PluginError(
                PluginError::AnyhowError(
                    anyhow!(e).context("Failed to rename temp directory to target"),
                ),
            ));
        }

        if old_path.exists() {
            async_fs::remove_dir_all(&old_path)
                .await
                .context("Failed to delete old directory")
                .map_err(|e| ProcessingEngineError::PluginError(PluginError::AnyhowError(e)))?;
        }

        Ok(db_name)
    }
}

#[derive(Debug)]
pub struct PluginFileInfo {
    pub plugin_name: Arc<str>,

View on GitHub (pinned to d28e26e048)

Solutions

  1. Check the underlying IO error and the plugin dir: permissions (writable by the server user) and free space
  2. Move --plugin-dir to a local POSIX filesystem; network mounts often lack reliable atomic rename
  3. Ensure exactly one server instance writes to the plugin dir and no external process locks files inside it
  4. Retry the replace after remediation — the rollback restored the old version, so state is consistent

Example fix

# before: plugin dir on an NFS volume with unreliable rename
influxdb3 serve --plugin-dir /mnt/nfs/plugins ...

# after: local writable volume
influxdb3 serve --plugin-dir /var/lib/influxdb3/plugins ...
Defensive patterns

Strategy: retry

Validate before calling

# preflight before a plugin update: writable dir, local FS, free space
DF=$(df -P /var/lib/influxdb3/plugins | awk 'NR==2 {print $4}')
test -w /var/lib/influxdb3/plugins && [ "$DF" -gt 1048576 ] \
  || { echo "plugin dir not writable or low on space" >&2; exit 1; }

Try / catch

match engine.replace_plugin_directory(name, files).await {
    Err(e) if e.to_string().contains("Failed to rename temp directory") => {
        // engine rolled back to the previous version; fix fs issue then retry once
        log::warn!("plugin replace rolled back: {e}");
        engine.replace_plugin_directory(name, files).await?
    }
    other => other?,
}

Prevention

When it happens

Trigger: rename(2) failing on the plugin directory: permission denied, the plugin dir living on a filesystem with broken rename semantics (some NFS/SMB mounts), the target held open by another process (Windows AV/indexers/another server instance), or disk/inode exhaustion during the swap.

Common situations: --plugin-dir on a network volume inside Kubernetes; two server processes pointed at the same plugin dir; permission changes after the server started; antivirus or backup jobs scanning the plugin dir mid-swap.

Related errors


AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16). Data as JSON: /api/errors/b17a8fefda711e11. Report an issue: GitHub.