This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 2eabbf906d Issue #8988 : Document running native Spark pipelines on a 
local Spark standalone cluster (#8989)
2eabbf906d is described below

commit 2eabbf906db56c6843079cc0e70811cb6399e165
Author: Bart Maertens <[email protected]>
AuthorDate: Mon Oct 19 09:16:51 2026 +0200

    Issue #8988 : Document running native Spark pipelines on a local Spark 
standalone cluster (#8989)
---
 docs/hop-user-manual/modules/ROOT/nav.adoc         |   1 +
 .../native-spark-pipeline-engine.adoc              |   2 +-
 .../spark/getting-started-with-native-spark.adoc   |  14 +-
 .../pipeline/spark/local-standalone-cluster.adoc   | 338 +++++++++++++++++++++
 4 files changed, 351 insertions(+), 4 deletions(-)

diff --git a/docs/hop-user-manual/modules/ROOT/nav.adoc 
b/docs/hop-user-manual/modules/ROOT/nav.adoc
index 0d82bbbdf5..29e5a12eec 100644
--- a/docs/hop-user-manual/modules/ROOT/nav.adoc
+++ b/docs/hop-user-manual/modules/ROOT/nav.adoc
@@ -70,6 +70,7 @@ under the License.
 *** xref:pipeline/beam/flink-k8s-operator-running-hop-pipeline.adoc[Running a 
Hop pipeline using the Flink Kubernetes Operator]
 *** xref:pipeline/beam/developing-beam-transforms.adoc[Developing a Beam 
transform]
 ** xref:pipeline/spark/getting-started-with-native-spark.adoc[Getting started 
with the native Spark engine]
+*** xref:pipeline/spark/local-standalone-cluster.adoc[Local standalone cluster]
 *** xref:pipeline/spark/paths-and-filesystems.adoc[Paths and file systems]
 *** xref:pipeline/spark/cluster-mapping-walkthrough.adoc[Cluster mapping 
walk-through]
 *** xref:pipeline/spark/lakehouse.adoc[Lakehouse tables (Delta / Iceberg)]
diff --git 
a/docs/hop-user-manual/modules/ROOT/pages/pipeline/pipeline-run-configurations/native-spark-pipeline-engine.adoc
 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/pipeline-run-configurations/native-spark-pipeline-engine.adoc
index aaba21c560..325e0e7ff9 100644
--- 
a/docs/hop-user-manual/modules/ROOT/pages/pipeline/pipeline-run-configurations/native-spark-pipeline-engine.adoc
+++ 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/pipeline-run-configurations/native-spark-pipeline-engine.adoc
@@ -49,7 +49,7 @@ Use **Load configuration template** to fill the fields below 
from a common deplo
 
 * *Local execution* — `local[*]`, Spark UI off (embedded Spark in Hop)
 * *Local (capped cores)* — `local[4]`
-* *Spark standalone server* — `spark://host:7077` (replace host), sample 
driver/executor memory
+* *Spark standalone server* — `spark://host:7077` (replace host), sample 
driver/executor memory. Also set *Fat jar file location* to a `native-provided` 
fat jar; the template leaves it empty. See 
xref:pipeline/spark/local-standalone-cluster.adoc[Local standalone cluster].
 * *spark-submit (cluster)* — master **empty** so `spark-submit --master` wins; 
use a `native-provided` fat jar
 * *Databricks* — submit-oriented placeholders (master empty); set 
workspace-specific values yourself
 * *YARN client* — master `yarn`, client deploy mode
diff --git 
a/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/getting-started-with-native-spark.adoc
 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/getting-started-with-native-spark.adoc
index fd9fc36309..7e168a13ca 100644
--- 
a/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/getting-started-with-native-spark.adoc
+++ 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/getting-started-with-native-spark.adoc
@@ -37,6 +37,9 @@ For **Simple Mapping** / **Pipeline Executor** child 
pipelines on `spark-submit`
 xref:pipeline/spark/paths-and-filesystems.adoc#spark-project-package[Spark 
project package]
 (`hop-conf -j … --export-spark-project=…`) and pass `--HopProjectPackage=…` to 
`MainSpark`.
 
+To run pipelines from Hop GUI or `hop-run` on a Spark standalone cluster on 
your own machine:
+xref:pipeline/spark/local-standalone-cluster.adoc[Local standalone cluster].
+
 Hands-on multi-node demo (Docker Compose + sample project `spark-demo` — 
Simple Mapping and Workflow Executor):
 xref:pipeline/spark/cluster-mapping-walkthrough.adoc[Cluster demo 
walk-through].
 
@@ -140,7 +143,8 @@ Do *not* mix this engine with Beam’s Spark 3.5 fat-jar 
packs or an accidental
 
 == Prerequisites
 
-* Apache Hop *2.19+* with the *engines-spark* plugin (standard Hop client / 
assembly includes it).
+* Apache Hop *2.19+* with the `hop-engines-spark` plugin. It is not part of 
the default client download: install it with `./hop marketplace install 
hop-engines-spark` (see xref:hop-tools/hop-marketplace.adoc[Hop Marketplace]) 
and restart Hop.
+* For cluster runs, also the `hop-engines-beam` plugin: the fat jar builder 
ships with it.
 * *Java 21*.
 * Familiarity with Hop pipelines, metadata, and run configurations.
 * For cluster submit:
@@ -227,9 +231,11 @@ On a real cluster you must *not* embed a second copy of 
Spark inside the applica
 
 Use the special fat-jar token *`native-provided`*: Hop and plugins go into the 
jar; *Spark stays out*.
 
+The fat jar builder ships with the Apache Beam engine plugin. Without 
`hop-engines-beam` installed, `hop-conf.sh` reports `Unknown options: 
'--generate-fat-jar=...'`.
+
 ==== From Hop GUI
 
-. *Tools* → *Generate a Hop fat jar* (when prompted for Spark client version 
for native submit, use the *native-provided* style packaging for cluster submit 
— or use the CLI below for an explicit flag).
+. Start Hop GUI with the environment variable 
`HOP_SPARK_CLIENT_VERSION=native-provided`. *Tools* → *Generate a Hop fat jar* 
does not ask for the packaging; without that variable it builds a jar for the 
Beam Spark runner, not for the native engine.
 . Save the jar *outside* the project (or gitignore it). Fat jars are large.
 
 ==== From the command line (recommended, explicit)
@@ -297,6 +303,8 @@ export SPARK_HOME=/path/to/spark-4.1.x-bin-hadoop3
   /path/to/cluster-env-config.json
 ----
 
+NOTE: Start `spark-submit` from a folder that does not contain a Hop `plugins` 
folder, not from the Hop installation folder. Otherwise Hop loads the Spark 
engine twice, from the fat jar and from that folder, and the run fails with 
`Run configuration '...' is not a native Spark pipeline engine configuration`. 
See 
xref:pipeline/spark/local-standalone-cluster.adoc#troubleshooting[Troubleshooting].
+
 *Main class:* `org.apache.hop.spark.run.MainSpark`
 
 *Positional arguments:*
@@ -449,7 +457,7 @@ Classic *Spark File* transforms cover `csv` / `parquet` / 
`json` / `orc` / `text
 * xref:pipeline/transforms/spark-lake-table-merge.adoc[Spark lake table merge] 
/ xref:pipeline/transforms/spark-lake-table-maintenance.adoc[Spark lake table 
maintenance]
 * xref:metadata-types/spark-catalog.adoc[Lakehouse catalog] metadata for 
Iceberg TABLE mode
 
-Connector JARs **ship in the default Hop assembly** under 
`plugins/engines/spark/lib/{delta,iceberg}` (and ride a *native-provided* fat 
jar for cluster submit). Full session conf, PATH vs TABLE, and samples: 
xref:pipeline/spark/lakehouse.adoc[Lakehouse tables on the native Spark engine].
+Connector JARs **ship with the `hop-engines-spark` plugin** under 
`plugins/engines/spark/lib/{delta,iceberg}` (and ride a *native-provided* fat 
jar for cluster submit). Full session conf, PATH vs TABLE, and samples: 
xref:pipeline/spark/lakehouse.adoc[Lakehouse tables on the native Spark engine].
 
 === Classic Hop I/O and `${Internal.Transform.ID}`
 
diff --git 
a/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/local-standalone-cluster.adoc
 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/local-standalone-cluster.adoc
new file mode 100644
index 0000000000..353ee26fe6
--- /dev/null
+++ 
b/docs/hop-user-manual/modules/ROOT/pages/pipeline/spark/local-standalone-cluster.adoc
@@ -0,0 +1,338 @@
+////
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+  http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+////
+[[NativeSparkLocalStandaloneCluster]]
+:imagesdir: ../../../assets/images
+:description: Start a Spark 4.1 standalone cluster on your own machine and run 
Hop pipelines on it with the native Spark engine, from Hop GUI or hop-run.
+:page-marketplace: hop-engines-spark
+
+:toc:
+
+= Run pipelines on a local Spark standalone cluster
+
+`local[*]` runs Spark inside the Hop process. A *standalone cluster* runs a 
Spark master and one or more workers as separate processes, the way a real 
cluster does: your pipeline is split into tasks, shipped to executors, and the 
Hop code those tasks need travels in a fat jar.
+
+This page sets up such a cluster on one machine and runs a pipeline on it from 
Hop GUI or `hop-run`. Hop is the Spark *driver*: you design and start the 
pipeline in Hop as usual, and the work runs on the workers.
+
+Do this after your first `local[*]` run (see 
xref:pipeline/spark/getting-started-with-native-spark.adoc[Getting started with 
the native Spark engine]). To submit with `spark-submit` inside Docker 
containers instead, see the 
xref:pipeline/spark/cluster-mapping-walkthrough.adoc[cluster demo walk-through].
+
+== What you need
+
+* Linux or macOS. Spark's start scripts are shell scripts; on Windows use WSL.
+* Java 21, both for Hop and for the Spark processes. Spark 4.1 also runs on 
Java 17, but the Hop classes in the fat jar need 21.
+* About 10 GB of free disk: 600 MB for Spark, 900 MB for the fat jar, and room 
for executor copies of that jar, about 3.5 GB per run (see <<disk-space>>).
+* A Hop client with the native Spark engine and the Apache Beam engine plugins 
(next section).
+
+== 1. Install the engine plugins
+
+The native Spark engine is not part of the default Hop client download. 
Install it from the xref:hop-tools/hop-marketplace.adoc[marketplace], together 
with the Apache Beam engine: the fat jar builder you need in step 3 ships with 
the Beam plugin.
+
+From the Hop installation folder:
+
+[source,bash]
+----
+./hop marketplace install hop-engines-spark hop-engines-beam
+----
+
+Restart Hop GUI if it was open. The new engine shows up as *Native Spark 
pipeline engine* in the *Engine type* list of a pipeline run configuration.
+
+The Beam plugin also adds the `beam` folder to the `samples` project. The 
example pipeline below reads its sample data from there.
+
+== 2. Start a Spark standalone cluster
+
+The cluster runs the same Spark version the engine is built with: *4.1.3*, 
Scala 2.13.
+
+=== Download Spark
+
+[source,bash]
+----
+mkdir -p ~/spark && cd ~/spark
+curl -fLO 
https://dlcdn.apache.org/spark/spark-4.1.3/spark-4.1.3-bin-hadoop3.tgz
+curl -fLO 
https://downloads.apache.org/spark/spark-4.1.3/spark-4.1.3-bin-hadoop3.tgz.sha512
+sha512sum -c spark-4.1.3-bin-hadoop3.tgz.sha512   # macOS: shasum -a 512 -c ...
+tar xzf spark-4.1.3-bin-hadoop3.tgz
+----
+
+If the `dlcdn` link no longer works, the release is kept at 
`https://archive.apache.org/dist/spark/spark-4.1.3/`.
+
+=== Configure the cluster
+
+Create `~/spark/spark-4.1.3-bin-hadoop3/conf/spark-env.sh`. The start scripts 
read it, so the settings apply every time you start or stop the cluster.
+
+[source,bash]
+----
+# Master on this machine only
+SPARK_MASTER_HOST=localhost
+
+# Two workers with 2 cores and 2 GB each. Size this to your machine.
+SPARK_WORKER_INSTANCES=2
+SPARK_WORKER_CORES=2
+SPARK_WORKER_MEMORY=2g
+
+# Executor scratch space. Keep it on a disk with room to spare, not on a small 
/tmp.
+SPARK_LOCAL_DIRS=$HOME/spark/local
+
+# Remove the folders of finished applications after an hour, checked every 10 
minutes
+SPARK_WORKER_OPTS="-Dspark.worker.cleanup.enabled=true 
-Dspark.worker.cleanup.interval=600 -Dspark.worker.cleanup.appDataTtl=3600"
+
+# Uncomment if java on your PATH is not Java 21
+# JAVA_HOME=/path/to/java-21
+----
+
+Why `SPARK_LOCAL_DIRS` and `SPARK_WORKER_OPTS` matter: every executor copies 
the fat jar into `SPARK_LOCAL_DIRS` (default `/tmp`) and again into the 
worker's `work` folder. See <<disk-space>>.
+
+=== Start the master and the workers
+
+[source,bash]
+----
+mkdir -p ~/spark/local
+export SPARK_HOME=~/spark/spark-4.1.3-bin-hadoop3
+$SPARK_HOME/sbin/start-master.sh
+$SPARK_HOME/sbin/start-worker.sh spark://localhost:7077
+----
+
+Open the master web UI at http://localhost:8080. It should list two workers in 
state `ALIVE`, with 4 cores and 4 GB in total. The master URL at the top of the 
page, `spark://localhost:7077`, is what Hop connects to.
+
+NOTE: Use `start-master.sh` and `start-worker.sh` as above, not 
`start-all.sh`: `start-all.sh` starts the workers over SSH, which you do not 
need on a single machine.
+
+== 3. Build the fat jar
+
+Executors do not have Hop installed. Hop sends them a *fat jar* with Hop and 
all its plugins when the pipeline starts. Build it with the `native-provided` 
mode, which leaves Spark out because the cluster already has it.
+
+Run this from the Hop installation folder:
+
+[source,bash]
+----
+./hop-conf.sh \
+  --generate-fat-jar=$HOME/spark/hop-native-provided.jar \
+  --spark-client-version=native-provided
+----
+
+This takes two to three minutes and produces a jar of roughly 900 MB.
+
+* Build the jar again after you install, remove, or upgrade plugins. The 
executors run the plugins in the jar, not the ones in your Hop installation.
+* Use the command line. *Tools* -> *Generate a Hop fat jar* in Hop GUI does 
not ask for the mode; it uses the `HOP_SPARK_CLIENT_VERSION` environment 
variable and, without it, builds a jar for the Beam Spark runner instead.
+
+If `hop-conf.sh` reports `Unknown options: '--generate-fat-jar=...'`, the Beam 
engine plugin is missing (step 1).
+
+== 4. Create the run configuration
+
+. In Hop GUI, open the `samples` project.
+. Create a new *Pipeline run configuration* in the metadata perspective and 
name it `spark-standalone`.
+. Set *Engine type* to *Native Spark pipeline engine*.
+. Click *Load configuration template* and choose *Spark standalone server*.
+. Change the engine options:
++
+[options="header",cols="1,2,3"]
+|===
+|Option |Value |Why
+
+|Spark master
+|`spark://localhost:7077`
+|The template uses `spark://host:7077` as a placeholder.
+
+|Fat jar file location
+|The absolute path of the jar from step 3, for example 
`/home/<you>/spark/hop-native-provided.jar` (`/Users/<you>/...` on macOS)
+|The template leaves this empty. Without it the executors cannot load Hop (see 
<<troubleshooting>>).
+
+|Executor memory
+|`1g`
+|Must fit in one worker (`SPARK_WORKER_MEMORY`).
+
+|Executor cores
+|`1`
+|With the cluster above this gives four executors of one core each.
+
+|Spark config (key=value lines)
+|`spark.ui.enabled=false` +
+`spark.driver.host=localhost`
+|The executors connect back to the driver, which is Hop. `localhost` keeps 
that connection on your machine, also when a VPN or several network interfaces 
are active.
+|===
+. Save the run configuration.
+
+The full option list is on the 
xref:pipeline/pipeline-run-configurations/native-spark-pipeline-engine.adoc[Native
 Spark pipeline engine] page.
+
+== 5. Build a pipeline
+
+The pipeline reads 1,000 sample customers, keeps those born before 1980, 
counts them per state, and writes one CSV file. Filter Rows runs as Hop code on 
the executors; Memory Group By and the two Spark File transforms run as Spark 
operations. A successful run therefore shows both that the cluster works and 
that the executors can load the fat jar.
+
+Create a new pipeline in the `samples` project and save it as 
`spark/customers-per-state.hpl`. Add four transforms and connect them in this 
order:
+
+. *Spark file input*, named `customers`:
+** *Spark path (Hadoop URI)*: 
`+${PROJECT_HOME}/beam/input/customers-noheader-1k.txt+`
+** *Format*: `csv`, *First line is header*: off, *Separator*: `;`, *Infer 
schema*: off
+** *Fields*, in this order:
++
+[options="header",cols="1,1"]
+|===
+|Name |Type
+|id |Integer
+|name |String
+|firstname |String
+|zip |String
+|city |String
+|birthdate |String
+|street |String
+|housenr |String
+|stateCode |String
+|state |String
+|===
+. *Filter rows*, named `born before 1980`: condition `birthdate` `<` the 
constant `1980/01/01` (type String). The dates are stored as `yyyy/MM/dd`, so 
comparing them as text gives the right answer. Leave the true and false targets 
empty: rows that do not match are dropped.
+. *Memory group by*, named `count per state`: group on `stateCode` and 
`state`; one aggregate named `customers`, type *Number of rows (without field 
argument)*.
+. *Spark file output*, named `customers-per-state`:
+** *Spark path / directory (Hadoop URI)*: 
`+${PROJECT_HOME}/output/customers-per-state+`
+** *Format*: `csv`, *Save mode*: `Overwrite`, *Write header*: on, *Coalesce 
partitions*: `1`
+
+Paths in Spark File transforms are Spark paths, not Hop VFS paths. On a single 
machine the driver and every executor see the same local files, so plain local 
paths work. Across machines, use storage every node can reach; see 
xref:pipeline/spark/paths-and-filesystems.adoc[Paths and file systems].
+
+== 6. Run it
+
+In Hop GUI, run the pipeline and choose the `spark-standalone` run 
configuration. Or, from the Hop installation folder:
+
+[source,bash]
+----
+./hop-run.sh -j samples -r spark-standalone \
+  -f config/projects/samples/spark/customers-per-state.hpl
+----
+
+With `hop-run`, every run is a new Spark application. Even this small pipeline 
takes about 20 seconds: the application starts new executors, and each one 
copies the fat jar before it starts working. While it runs, the master UI at 
http://localhost:8080 lists the application under *Running Applications*, and 
when it is done under *Completed Applications* with state `FINISHED`. Click the 
application ID to see its executors and their logs. The executors show state 
`KILLED`: that is how a st [...]
+
+From Hop GUI, the first run starts the application and Hop GUI keeps it 
running, with all its cores, until you close Hop GUI. Later runs from Hop GUI 
reuse it. Close Hop GUI before you run on the cluster with `hop-run` or through 
Hop Server (step 7), or those runs wait for cores.
+
+The Spark application UI (jobs, stages and tasks, normally on port 4040) is 
not available: Hop turns it off for the Spark sessions it starts.
+
+The log shows the session connecting to the cluster:
+
+[source]
+----
+Created SparkSession version=4.1.3 master=spark://localhost:7077 (owned)
+...
+Spark pipeline finished, result row count=0
+----
+
+The log also warns that a Spark File path references `PROJECT_HOME`. That 
warning is about 
xref:pipeline/spark/paths-and-filesystems.adoc#spark-project-package[Spark 
project packages] for `spark-submit`; on a single machine you can ignore it.
+
+The result is one CSV part file under 
`config/projects/samples/output/customers-per-state/`:
+
+[source,bash]
+----
+cat config/projects/samples/output/customers-per-state/part-*.csv
+----
+
+It has a header line and one line per state with the number of customers born 
before 1980.
+
+[[hop-server]]
+== 7. Optional: run it through Hop Server
+
+To run the pipeline on the cluster from a xref:hop-server/index.adoc[Hop 
Server] instead of from your own Hop process, let Hop Server run a workflow 
whose *Pipeline* action uses the `spark-standalone` run configuration. Hop 
Server then becomes the Spark driver.
+
+A workflow is needed for this pipeline: `hop-run` refuses to send pipelines 
with Spark File or Lake table transforms to a remote pipeline run 
configuration. Pipelines without those transforms can also use a pipeline run 
configuration with the *Hop remote pipeline engine*.
+
+. Start Hop Server from the Hop installation folder, with the `samples` 
project enabled:
++
+[source,bash]
+----
+./hop-server.sh -j samples localhost 8181
+----
++
+Port 8181 because the Spark master UI already uses 8080 and the workers use 
8081 and 8082. The default user and password are `cluster` / `cluster`.
+. In Hop GUI, create a *Hop Server* metadata object named `spark-hop-server`: 
*Hostname or IP address* `localhost`, *Port* `8181`, *Username* `cluster`, 
*Password* `cluster`. The `local-hop-server` object in the samples project uses 
port 8080, which the Spark master has taken.
+. Create a *Workflow run configuration* named `remote-server`:
+** *Workflow engine type*: *Hop remote workflow engine*
+** *Hop server*: `spark-hop-server`
+** *Run Configuration*: `local`
+** *Export linked resources to server*: on. The workflow and pipeline are then 
sent as files. With it off, the samples project's Workflow Log fails every 
workflow you send to Hop Server (see <<troubleshooting>>).
+. Create a workflow and save it as `spark/run-customers-per-state.hwf`: a 
*Start* action, then a *Pipeline* action with *Pipeline* 
`+${PROJECT_HOME}/spark/customers-per-state.hpl+` and *Run configuration* 
`spark-standalone`.
+. Run the workflow with the `remote-server` run configuration, from Hop GUI or 
from the Hop installation folder:
++
+[source,bash]
+----
+./hop-run.sh -j samples -r remote-server \
+  -f config/projects/samples/spark/run-customers-per-state.hwf
+----
+
+The Hop Server status page at http://localhost:8181/hop/status/ lists the 
workflow as `Finished`, and the same CSV file as in step 6 is written.
+
+Like Hop GUI, Hop Server keeps the Spark application it started running until 
Hop Server stops. Later native Spark runs on that Hop Server reuse it: they 
start faster, but they also run with the master, fat jar and Spark config of 
the first run, and on the cluster the application keeps its cores. The Spark 
master UI shows it under *Running Applications*. Restart Hop Server after you 
change a native Spark run configuration, and stop it when you need the cluster 
for other work.
+
+== Stop the cluster
+
+[source,bash]
+----
+export SPARK_HOME=~/spark/spark-4.1.3-bin-hadoop3
+$SPARK_HOME/sbin/stop-worker.sh
+$SPARK_HOME/sbin/stop-master.sh
+----
+
+`stop-worker.sh` reads `SPARK_WORKER_INSTANCES` from `spark-env.sh` and stops 
both workers.
+
+[[disk-space]]
+== Disk space
+
+Every executor copies the fat jar twice:
+
+* into `SPARK_LOCAL_DIRS` while it fetches it. With the default `/tmp`, a few 
parallel copies of a 900 MB jar can fill a small or quota-limited `/tmp` (for 
example a `tmpfs`). The executors then fail with `Disk quota exceeded` or `No 
space left on device`, and Spark keeps starting new executors that fail the 
same way, so the pipeline never ends. Stop it, set `SPARK_LOCAL_DIRS` to a 
folder on disk, and restart the workers.
+* into the worker's `work/<application id>/<executor id>/` folder, where it 
stays after the application ends. Four executors use about 3.5 GB per run. The 
`spark.worker.cleanup.*` settings in `spark-env.sh` remove those folders some 
time after an application has finished. You can also delete 
`~/spark/spark-4.1.3-bin-hadoop3/work/app-*` yourself while no application is 
running.
+
+[[troubleshooting]]
+== Troubleshooting
+
+[options="header",cols="2,3"]
+|===
+|Symptom |Cause and fix
+
+|`hop-conf.sh` reports `Unknown options: '--generate-fat-jar=...'`
+|The fat jar builder ships with the Beam engine plugin. Install 
`hop-engines-beam` (step 1).
+
+|*Native Spark pipeline engine* is not in the *Engine type* list
+|Install `hop-engines-spark` and restart Hop.
+
+|The run fails with `ClassCastException: cannot assign instance of 
java.lang.invoke.SerializedLambda to field 
org.apache.spark.rdd.MapPartitionsRDD.f`
+|The executors cannot load Hop classes: *Fat jar file location* is empty or 
points to a file that does not exist.
+
+|Executors fail with `Disk quota exceeded` or `No space left on device`, and 
the run never ends
+|`SPARK_LOCAL_DIRS` is on a full or small file system. See <<disk-space>>.
+
+|The run never progresses and the master UI shows the application as `WAITING` 
with 0 cores
+|Another application holds the cores: check *Running Applications* in the 
master UI. Hop GUI and Hop Server keep their Spark application until they stop; 
close or stop them. Otherwise no worker can start an executor of the requested 
size: lower *Executor memory* and *Executor cores* to fit `SPARK_WORKER_MEMORY` 
and `SPARK_WORKER_CORES`, and check that the workers are `ALIVE`.
+
+|`[PATH_NOT_FOUND] Path does not exist` from Spark file input
+|The path must exist on the machine where each executor runs. Check the 
variables the path uses.
+
+|The log shows `Prepared native Spark pipeline engine` with the master you 
expect, then `Reusing active SparkSession` or `Reusing default SparkSession`, 
and the run uses a different master or an older application
+|An earlier native Spark run in the same Hop GUI, Hop Server or workflow left 
its Spark session running, and this run reuses it with that run's master, fat 
jar and Spark config. Restart Hop GUI or Hop Server after switching between 
native Spark run configurations.
+
+|After a run from Hop GUI or through Hop Server, the application stays under 
*Running Applications* in the Spark master UI and keeps its cores
+|Expected: Hop GUI and Hop Server keep their Spark application until they stop 
(see step 6 and <<hop-server>>). Close Hop GUI or restart Hop Server to release 
the cluster.
+
+|`hop-run` reports `Engine 'Remote' has <n> incompatible transform(s)` for a 
remote pipeline run configuration
+|Pipelines with Spark File or Lake table transforms cannot be sent with a 
remote pipeline run configuration. Run them through a workflow on Hop Server 
(see <<hop-server>>).
+
+|A workflow on Hop Server fails at the start with `NullPointerException: 
Cannot invoke "String.replaceAll(String, String)" because "vfsFilename" is null`
+|The project has a *Workflow Log* that lists specific workflows (the samples 
project does), and the workflow was sent without its file. Turn on *Export 
linked resources to server* in the remote workflow run configuration, or 
disable the Workflow Log.
+
+|`spark-submit` fails with `Run configuration '...' is not a native Spark 
pipeline engine configuration (found 
org.apache.hop.spark.engines.SparkPipelineRunConfiguration)`
+|`spark-submit` was started from a folder that contains a Hop `plugins` 
folder, such as the Hop installation folder. Hop then loads the Spark engine 
twice: from the fat jar and from that folder. Start `spark-submit` from another 
folder.
+|===
+
+== Related pages
+
+* xref:pipeline/spark/getting-started-with-native-spark.adoc[Getting started 
with the native Spark engine]
+* 
xref:pipeline/pipeline-run-configurations/native-spark-pipeline-engine.adoc[Native
 Spark pipeline engine] (option reference)
+* xref:pipeline/spark/paths-and-filesystems.adoc[Paths and file systems on 
native Spark]
+* xref:pipeline/spark/cluster-mapping-walkthrough.adoc[Cluster demo 
walk-through] (Docker, `spark-submit`)
+* xref:hop-tools/hop-marketplace.adoc[Hop Marketplace]
+* https://spark.apache.org/docs/4.1.3/spark-standalone.html[Spark standalone 
mode] (Apache Spark documentation)

Reply via email to