Hello @capoorhimanshu
On standard access mode this is expected. Scala/Java closures (foreachPartition, mapPartitions, UDFs) don't run in the executor JVM where the cluster env vars are set. They run in an isolated per-user sandbox process with a fixed, minimal environment. That's the 3@sandbox process and the 27 vars you're seeing. On DBR 19 spark.executorEnv.* is also restricted on standard, so you can't push the vars that way. The supported fix is to read the value on the driver and pass it into the closure, or to run the job on dedicated access mode.
Option 1: capture on the driver. This works on standard mode, DBR 16.4 and 19:
final String password = System.getenv("MY_PASSWORD"); // driver: present
ds.foreachPartition((ForeachPartitionFunction<Row>) rows -> {
// 'password' is serialized with the task closure
try (Connection c = DriverManager.getConnection(url, user, password)) {
while (rows.hasNext()) { /* ... */ }
}
});
Keep it in a local final variable (not a static field), or the sandbox will just see null. It travels inside the serialized task, so don't log or toString() the closure. Spark's redaction won't touch it there.
Option 2: dedicated (single user) access mode. Executors there run your code in their own JVM, which gets the cluster's environment variables, so System.getenv("MY_PASSWORD") works inside mapPartitions unchanged. This is the cleaner choice if the job runs as a service principal anyway.
About the docs line saying non-predefined variables "remain available to your user code, including UDFs": your repro shows that doesn't hold for JVM closures on standard. It's worth sending docs feedback on https://docs.databricks.com/aws/en/compute/standard-limitations so it gets clarified.
If this helps you and solves your problem , kindly accept them as answer so that community can be benefited