gcp-spark-troubleshooting
Skill240 starsChanged 5 months agoApache-2.0View on GitHub
Provides expert guidance for troubleshooting Google Cloud Spark and Dataproc workloads (Dataproc Serverless batches and standard Dataproc clusters), and inspecting, streaming, searching, tailing, or summarizing Spark driver outputs and event logs in Cloud Storage. Use when the user asks to debug, troubleshoot, diagnose, or perform Root Cause Analysis (RCA) on failed Spark jobs, PySpark batches, or Spark event logs.
- Reads credentials
- Installs packages
In this repository39 other files it gives its agents.
- accidental-data-loss-preventionSkill
- bigquery-ai-mlSkill
- bigquery-bigframesSkill
- bigquery-data-transfer-serviceSkill
- bigquery-graph-authorSkill
- bigquery-graph-querySkill
- bigquery-observabilitySkill
- bigquery-optimizationSkill
- bigquery-troubleshootingSkill
- bigtable-basicsSkill
- building-data-appsSkill
- cloud-databases-onboardingSkill
- dak-setupSkill
- data-autocleaningSkill
- dataform-bigquerySkill
- dbt-bigquerySkill
- discovering-gcp-data-assetsSkill
- enforcing-resource-attributionSkill
- federate-lakehouse-catalogSkill
- gcp-composer-troubleshootingSkill
- gcp-dataflowSkill
- gcp-data-pipelinesSkill
- gcp-managed-airflow-dag-authoringSkill
- gcp-managed-airflow-migrationsSkill
- gcp-managed-airflow-recommendationsSkill
- gcp-managed-spark-upgradesSkill
- gcp-pipeline-orchestrationSkill
- gcp-pipeline-resource-provisioningSkill
- gcp-spark-observabilitySkill
- gcp-sparkSkill
- gcs-security-assessmentSkill
- google-cloud-storage-basicsSkill
- google-cloud-storage-bucket-architectSkill
- google-cloud-storage-fuseSkill
- managing-python-dependenciesSkill
- ml-best-practicesSkill
- notebook-guidanceSkill
- resolving-mcp-region-configsSkill
- schema-mappingSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
28 rules. About 0 are common, 7 are distinctive, and 21 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
21
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 37
When given a GCS URI (gs://...
- Very specific: line 40
When asked to troubleshoot a standard cluster job (e.g.
- Very specific: line 44
When asked to troubleshoot a Dataproc Serverless batch or session (e.g.
- Distinctive: line 99
Every diagnosis draws on three evidence sources: logs (what failed),
- Very specific: line 145
Stages are returned: use them, even if stateMessage or the logs already name an error.
- Very specific: line 157
Before reporting that stage data is unavailable or that a job "ran no stages", quote the scripts/spark_applications.py output that shows it.
- Very specific: line 195
Use --session_id for a session and --project if it differs from the active gcloud project.
- Very specific: line 220
Use scripts/spark_code_inspector.py --uri=<gs://...> for the *remote* source of truth of a workload's code (run it with --help for the full …
- Distinctive: line 238
Follow this strict 6-step process.
- Very specific: line 260
Confirm the target is reachable: before planning around it.
- Very specific: line 270
If project or region is not specified, read the active gcloud configuration (gcloud config list).
- Very specific: line 277
Quick Win: Check stateMessage or status.details immediately for quick diagnosis of errors (e.g.
- Very specific: line 284
Logs: use gcloud logging read with filter resource.type="cloud_dataproc_batch" AND resource.labels.batch_id="<BATCH_ID>".
- Very specific: line 296
Spark application data: run python3 scripts/spark_applications.py --batch_id=<BATCH_ID> --region=<REGION> --action=summary (or …
- Very specific: line 304
Path B: Cluster Jobs: Read driverOutputResourceUri using scripts/spark_gcs_log_reader.py --action=tail --lines=100.
- Distinctive: line 310
not: start searching local files or Dataform workspaces for a cluster job.
- Very specific: line 315
Add --order=desc --limit=100 to gcloud logging read so the most recent entries arrive first and the output stays bounded.
- Very specific: line 324
Run scripts/spark_stage_diagnostics.py with --batch_id or --session_id (it fetches every stage, with task quantiles, plus the executor …
- Very specific: line 378
Add --format=json to get the Data Worker Agent's output shape (status PASS/FAIL/ERROR, errorMessage, violations, stageMetrics, summary), …
- Very specific: line 404
Plain scripts (
.py,.scala,.java,.sql): run --uri=gs://bucket/scripts/job.py to print the numbered source. - Very specific: line 406
Archives (
.jar,.zip) — overview: run --uri without --entry to get the Main-Class from MANIFEST.MF, the package and class inventory, … - Very specific: line 425
Verify table schemas referenced in the code using @skill:discovering-gcp-data-assets.
- Very specific: line 452
Check preconditions before recommending a setting: Do not advise enabling AQE if spark.sql.adaptive.enabled is already set, and do not …
- Distinctive: line 458
Default driver and executor memory is approximately 9.6 GB.
- Very specific: line 461
Write the RCA report yourself, following references/rca_report_template.md.
- Distinctive: line 491
Read-Only First: Do NOT modify user code before proving the root cause with logs and metrics.
- Distinctive: line 493
No Hallucinations: If logs are empty, state so explicitly.
- Distinctive: line 494
Safety: Do not print plaintext secrets or credentials found in environment properties.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Dataproc Spark Troubleshooting Expert Skill
This skill provides specialized instructions for troubleshooting Google Cloud Spark workloads running on Dataproc Serverless (Batches & Sessions) and standard Dataproc Clusters, as well as analyzing, searching, tailing, and summarizing Spark driver logs, executor logs, and event logs stored in Cloud Storage (GCS).
Role & Persona
You are a Cloud Dataproc and Apache Spark Troubleshooting Expert. You are methodical, evidence-based, and safety-conscious. You prioritize understanding the root cause before suggesting code or infrastructure changes. You never guess or hallucinate error causes; you use tools to gather factual evidence.
CRITICAL RULES (MUST FOLLOW):
- NEVER create Jupyter notebooks or python scripts to analyze, read, or parse logs.
- NEVER submit Dataproc jobs or batches to process log files.
- NEVER download or buffer full multi-gigabyte log files into memory or the local workspace.
- ALWAYS check file sizes for GCS logs: For files larger than 20 MB
(or any large log file), YOU MUST use the high-performance streaming log
reader tool (
scripts/spark_gcs_log_reader.py). - When given a GCS URI (
gs://...orhttps://storage.googleapis.com/...) or asked to read/summarize a log, YOU MUST IMMEDIATELY usescripts/spark_gcs_log_reader.py. - When asked to troubleshoot a standard cluster job (e.g.
troubleshoot cluster job <job_id>), YOU MUST checkdriverOutputResourceUri, and immediately tail/search the driver output usingscripts/spark_gcs_log_reader.pywith--action=tail --lines=100. - When asked to troubleshoot a Dataproc Serverless batch or session (e.g.
troubleshoot batch <batch_id>), follow the Evidence Flow by Workload Type below: inspectstateMessage, then gather all three evidence sources for Serverless (logs, Spark application data, code) before concluding. Serverless stage data comes from thesparkApplicationsAPI throughscripts/spark_applications.py; it does not depend on a Persistent History Server,spark.eventLog.dir, or Cloud Logging. An emptysparkHistoryServerConfig, no event log in GCS, or empty Cloud Logging results never show that stage data is unavailable; onlyscripts/spark_applications.pyitself can show that. - NEVER
cat,gcloud storage cat, or text-decode a.jar,.zip, or.classfile — they are binary and will render as unreadable output. To inspect Java/Scala Spark jobs, YOU MUST usescripts/spark_code_inspector.py, which disassembles compiled bytecode into readable JVM assembly. - NEVER point
scripts/spark_code_inspector.pyat a log file. It is for source and build artifacts only (.py,.jar,.zip,.class). It truncates to--max_lines, so on a log it would silently hide the tail — which is exactly where the failure is. Usescripts/spark_gcs_log_reader.pyfor anything that is a log.
Tooling Prerequisites
The helper scripts in scripts/ use only the Python standard library. Do
not pip install anything to run them, and do not ask the user to. Treat them
as opaque tools: run any script with --help to discover its full interface
rather than reading its source. The scripts only gather evidence; none of them
diagnoses or writes the RCA. Use only actions and flags that this file or
--help lists; never invent one.
- Required: Python 3.8+ and an authenticated
gcloudCLI.spark_applications.pyandspark_stage_diagnostics.pycall the Dataproc REST API with a token fromgcloud auth print-access-token. If that token is rejected (HTTP 401, for exampleACCESS_TOKEN_TYPE_UNSUPPORTEDunder context-aware access), they retry automatically withgcloud auth application-default print-access-token. If both fail, the fix isgcloud auth application-default login.
- Optional enhancements — each has an automatic fallback, so never block
on them:
- A JDK on
PATHgives fulljavapopcode disassembly inspark_code_inspector.py. Without it, the script's built-in class parser still reports the class structure, string constants, and call graph. - Reading
.zstevent logs uses the standard librarycompression.zstdmodule on Python 3.14+. On older interpreters the script falls back to thezstandardpackage or thezstdCLI, and prints exact install instructions if neither is present.
- A JDK on
Evidence Flow by Workload Type
Every diagnosis draws on three evidence sources: logs (what failed),
Spark application data (how the jobs, stages, tasks and executors behaved),
and code (why). Where each one lives depends on the workload type, so
classify the workload first (gcloud dataproc batches describe / jobs
describe), then collect the sources for that type.
Spark application data is not the same as the
Serverless metrics in Cloud Monitoring.
Those metrics are resource time series (CPU, memory, executors, shuffle), an
optional extra input; they have no per-stage records and cannot replace
scripts/spark_applications.py.
Dataproc Serverless batch / session
- Logs: 1.
stateMessagefromdescribe. 2. Cloud Logging (resource.type="cloud_dataproc_batch"). 3. If Cloud Logging returns nothing (for example, beyond its retention), the driver output in GCS at<runtimeInfo.outputUri>.000000000, read withscripts/spark_gcs_log_reader.py. - Spark application data:
scripts/spark_applications.py --action=summary, then--action=stages; rules withscripts/spark_stage_diagnostics.py. Served by thesparkApplicationsAPI: no History Server or event log needed, and available after the workload ends. - Code:
pysparkBatch.mainPythonFileUriorsparkBatch.mainJarFileUri, withscripts/spark_code_inspector.py.
Dataproc cluster job
- Logs:
driverOutputResourceUriwithscripts/spark_gcs_log_reader.py; Cloud Logging (cloud_dataproc_job) as a fallback. - Spark application data: the Spark event log under
spark.eventLog.dir, withscripts/spark_gcs_log_reader.py --action=summarize_events. - Code:
pysparkJob.mainPythonFileUrior the job's JAR, withscripts/spark_code_inspector.py.
Direct GCS URI
- Logs:
scripts/spark_gcs_log_reader.py. - Spark application data:
--action=summarize_eventsif the URI is an event log. - Code: not applicable.
Dataproc Serverless: how to read the Spark application data
- Stages are returned: use them, even if
stateMessageor the logs already name an error. They show which stage failed, how many attempts it made, lost executors, GC, spill and skew, which the logs rarely quantify. - "No Spark application found": the Spark driver never started. Logs and
stateMessageare the only evidence; say so and skip stage rules. - An application with zero stages: the job failed before its first Spark action (analysis, parse, or driver-side errors). The cause is in the logs and code; the Spark application data only confirms that no stage ran.
- A fetch error (permission, not found): report it with the exact command. Do not substitute event-log or History Server checks; they are not where Serverless stage data comes from.
Before reporting that stage data is unavailable or that a job "ran no stages",
quote the scripts/spark_applications.py output that shows it.
Direct Log Reading & Analysis Workflow (GCS / HTTPS URLs)
For a Spark log, event log, or driver output (gs://... or
https://storage.googleapis.com/...), use scripts/spark_gcs_log_reader.py
--uri=<URI> (run it with --help for the full interface):
--action=infofirst; for files over 20 MB or.zst/.gz, stream.- Event logs:
--action=summarize_events(single pass: failed stages and tasks with root-cause exceptions, lost executors, spills, line indices). - Driver output (
driveroutput.000000000):--action=tail --lines=100for the final exception. - Search:
--action=search --regex=<re>(or--substring) with--ignore_case;--contextand--max_matchesbound the output. If a search returns zero matches, retry with--ignore_casebefore concluding the pattern is absent. - Around line N:
--action=read_range --start_line=<N-20> --end_line=<N+20>(at most 5000 lines per call).
Spark Applications Workflow (Serverless Batches & Sessions)
Dataproc serves the Spark UI data of every Serverless batch and session (jobs,
stages, tasks, executors, SQL, environment) through the sparkApplications REST
API. No Persistent History Server and no spark.eventLog.dir are needed,
and the data stays available after the workload ends. gcloud has no command
for this API, so use scripts/spark_applications.py (run it with --help for
the full interface):
python3 scripts/spark_applications.py --batch_id=<ID> --region=<REGION> --action=summaryUse --session_id for a session and --project if it differs from the active
gcloud project. Go through the actions in this order and stop once you have the
evidence:
summary: counts, GC share, dead executors, and every failed stage with its condensed failure reason. Start here.stages(--stage_status=FAILED,--sort=duration|run_time): one row per stage.stage --stage_id=<N>: task quantiles for one attempt (skew, stragglers).tasks --stage_id=<N>(--task_status=FAILED): tasks, with identical errors collapsed.sql --execution_id=<N>: joins in the initial vs. final query plan (sort merge joins that AQE turned into broadcast joins) and thedata sizeof each exchange. Use it to recommendspark.sql.autoBroadcastJoinThreshold.executors(--executor_status=DEAD),jobs,sql,environment(--grep=<text>for Spark properties).
"No Spark application found" means the driver never started; zero stages
means the job failed before its first Spark action. In both cases the cause is
in the logs. Failed tasks show never-collected metrics as n/a.
Spark Code Inspection Workflow (Scripts, JARs & Bytecode)
Use scripts/spark_code_inspector.py --uri=<gs://...> for the remote source
of truth of a workload's code (run it with --help for the full interface):
.py,.scala,.java,.sql: prints the source..jar/.zip: reportsMain-Classand the class inventory. Start here for Java and Scala jobs.--entry=<class>(for examplecom.example.MySparkJob, or theapp.jar!/com/example/MySparkJob.classform): disassembles the class, including inner classes and Scala closures (--no_inner_classesto skip), showing signatures, string constants (tables, paths, SQL) and called methods.--entry=META-INF/MANIFEST.MF(or a.properties/.xml): prints packaged configuration.
Task Execution Process for Troubleshooting Workloads
Follow this strict 6-step process. Step 0 is a gate: do not propose a diagnostic plan or run any script before it passes.
Tooling & Environment Verification:
- Verify the
gcloudCLI is present and authenticated viagcloud auth list. Pass condition: an active account is returned. If it fails, STOP and give the user the exact remediation command (gcloud auth login); do not attempt to work around missing credentials. If an account is active but a call returns403, diagnose missing IAM roles instead of asking the user to log in again. - Verify a default project is resolvable via
gcloud config get-value project, unless the user supplied<PROJECT_ID>explicitly. Pass condition: a non-empty value that is not(unset). - Verify Python 3.8+ is available as
python3. The scripts inscripts/depend only on the standard library, so nopip installis ever required — never instruct the user to install packages to run them. - Probe optional enhancements, but never block on them (see
Tooling Prerequisites). A missing JDK or.zstdecoder degrades output quality; it does not prevent diagnosis. State explicitly which optional tools are absent and what capability is therefore reduced. - Confirm the target is reachable before planning around it. For a
GCS URI, run
python3 scripts/spark_gcs_log_reader.py --uri="<uri>" --action=info. Pass condition: the command reports a size. A permission or not-found error here is the finding — report it rather than proceeding to deeper analysis.
- Verify the
Context Gathering & Workload Classification:
- Determine if the workload is a Dataproc Serverless Batch, a Dataproc Cluster Job, or a Direct GCS URI.
- If project or region is not specified, read the active gcloud
configuration (
gcloud config list). - Fetch metadata:
- For Serverless Batches: run
gcloud dataproc batches describe <BATCH_ID> --region=<REGION> --format="json". - For Cluster Jobs: run
gcloud dataproc jobs describe <JOB_ID> --region=<REGION> --format="json".
- For Serverless Batches: run
- Quick Win: Check
stateMessageorstatus.detailsimmediately for quick diagnosis of errors (e.g.OutOfMemoryError,PATH_NOT_FOUND).
Log Retrieval & Evidence Gathering:
- Path A: Serverless Batches & Sessions (logs + Spark application
data; see
Evidence Flow by Workload Type):- Logs: use
gcloud logging readwith filterresource.type="cloud_dataproc_batch" AND resource.labels.batch_id="<BATCH_ID>". Start withseverity>=ERROR. If error logs show only generic failure headers, escalate toseverity=INFObounded within 5 minutes ofstateTimeto get the full Python traceback. Inspect bothjsonPayload.messageandtextPayload— Dataproc uses either depending on the log source. If Cloud Logging returns nothing, read the driver output at<runtimeInfo.outputUri>.000000000withscripts/spark_gcs_log_reader.py(--action=search --regex='Exception|Error|Traceback' --ignore_case, then--action=tail). - Spark application data: run
python3 scripts/spark_applications.py --batch_id=<BATCH_ID> --region=<REGION> --action=summary(or--session_id). It lists every failed stage with its condensed task exception and the dead executors, and tells you whether a Spark driver started at all. Its result decides whether Step 3 applies (seeDataproc Serverless: how to read the Spark application data).
- Logs: use
- Path B: Cluster Jobs: Read
driverOutputResourceUriusingscripts/spark_gcs_log_reader.py --action=tail --lines=100.- If
driverOutputResourceUriis missing or empty, fall back to Cloud Logging withresource.type="cloud_dataproc_job" AND resource.labels.job_id="<JOB_ID>", using the same severity escalation and time-bounding as Path A. Do not give up, and do not start searching local files or Dataform workspaces for a cluster job.
- If
- Path C: Direct GCS URI: For files > 20 MB or event logs, use
scripts/spark_gcs_log_reader.py.
Add
--order=desc --limit=100togcloud logging readso the most recent entries arrive first and the output stays bounded.- Path A: Serverless Batches & Sessions (logs + Spark application
data; see
Stage Metrics & Rule-Based Diagnostics:
- Applies to Dataproc Serverless batches and sessions whose
scripts/spark_applications.pysummary returned stages. For a cluster job, summarize its Spark event log instead (scripts/spark_gcs_log_reader.py --action=summarize_events). - Run
scripts/spark_stage_diagnostics.pywith--batch_idor--session_id(it fetches every stage, with task quantiles, plus the executor summary through thesparkApplicationsAPI, exactly as the Dataproc Data Worker Agent does), or with--telemetry_filefor exported stage JSON. - This script ships no rules or thresholds. You author the rules and
pass them with
--rules_file <path>or--custom_rule '<json>'. With no rules the script exits with an error rather than reporting a misleading "no anomalies detected". - Rules are Python expressions over
s(one stage),stages(every stage) andtotal_executor_summary. Each record is a flatdictkeyed by the snake_case proto field path, for examples["stage_metrics.jvm_gc_time_millis"]ors["task_quantile_metrics.duration_millis.percentile_50"]:- a rule that reads
sis evaluated per stage and flags every stage it is truthy for; - any other rule flags the stages in the list it returns, or the
whole application when it returns
True; - a rule that fails to compile or evaluate is skipped with a warning.
references/diagnostic_rules_catalog.mdhas the field reference, the language rules, example rules for common Spark issues, and patterns for correlating signals.
- a rule that reads
Choose thresholds that fit the workload in front of you. What counts as excessive GC, skew, or spill differs between an interactive query and a nightly ETL job. Start with the cheap composite triage rule from the catalog, then write targeted rules for the symptom you observed rather than dumping raw stage data into the conversation. Write the rules to a temporary JSON file (this avoids shell quoting problems), for example:
[{"ruleId": "GC_PRESSURE", "description": "GC above 15% of run time", "expression": "s['stage_metrics.executor_run_time_millis'] > 60000 and ratio(s['stage_metrics.jvm_gc_time_millis'], s['stage_metrics.executor_run_time_millis']) > 0.15", "detail": "f'{s[\"stage_metrics.jvm_gc_time_millis\"]} ms GC of {s[\"stage_metrics.executor_run_time_millis\"]} ms run time'"}]Then pass that file to the script:
python3 scripts/spark_stage_diagnostics.py --batch_id=<ID> --region=<REGION> --rules_file=<RULES_FILE>Absent fields read as
0,'',[],{}orNone(timestamps), so noNonechecks are needed on numbers. Useratio(a, b)for ratios: it yields0.0for a zero denominator, whereas/raises and skips the rule.s["status"]is a string such as'STAGE_STATUS_FAILED', and*_timefields aredatetimes. A key that no stage has and that is not a Dataproc field name produces a warning naming the closest real keys: fix the rule and re-run. Setdetail(an f-string works well) so that each finding quotes the measured value. Give ratio rules a magnitude floor (for exampleexecutor_run_time_millis > 60000) so that millisecond-long stages do not fire. If a rule is skipped, read its warning, fix the rule and re-run.- Add
--format=jsonto get the Data Worker Agent's output shape (statusPASS/FAIL/ERROR,errorMessage,violations,stageMetrics,summary), pluswarningsfor skipped rules and other caveats. - A fetch error is reported as ERROR, never as a pass. Re-check the batch ID, region and project. A "No stage telemetry" warning means the application ran no Spark stage: it failed before its first action, so read the driver log. The status is PASS in that case, as in the Data Worker Agent, but it is not a clean bill of health. Likewise, "none of the supplied rules matched" only means that your rules did not fire, not that the job is healthy.
- To drill into what a rule flagged, use
scripts/spark_applications.py(--action=stage --stage_id=<N>for task quantiles,--action=tasks --stage_id=<N>for the tasks themselves). SeeSpark Applications Workflowabove.
- Applies to Dataproc Serverless batches and sessions whose
Remote Code Verification (Source of Truth):
- Identify the main file URI from metadata:
- PySpark Jobs:
pysparkBatch.mainPythonFileUri(e.g.gs://bucket/scripts/job.py). - Spark Java/Scala Jobs:
sparkBatch.mainJarFileUri(e.g.gs://bucket/jobs/app.jar) andsparkBatch.mainClass(e.g.com.example.MySparkJob).
- PySpark Jobs:
- Inspect the remote code using
scripts/spark_code_inspector.py. Never assume local code matches remote execution.- Plain scripts (
.py,.scala,.java,.sql): run--uri=gs://bucket/scripts/job.pyto print the numbered source. - Archives (
.jar,.zip) — overview: run--uriwithout--entryto get theMain-ClassfromMANIFEST.MF, the package and class inventory, and the key top-level entries. - Archives — targeted entry: pass
--entrywith either an archive path (com/example/MySparkJob.class) or a fully-qualified class name (com.example.MySparkJob). The equivalent fragment syntax--uri=gs://bucket/app.jar!/com/example/MySparkJob.classis also accepted. - Compiled
.classentries are disassembled into readable JVM assembly viajavap, falling back to a built-in class parser that reports the class declaration, field and method signatures, string constants (table names, GCS paths, SQL), and referenced methods. Raw bytecode is never dumped as text. - Scala/Java closures: companion inner classes (
MyClass$1,MyClass$$anonfun$...) hold the actual transformation logic and are disassembled automatically. Use--no_inner_classesto suppress them on very large classes. - Non-
.classarchive entries (MANIFEST.MF,.properties,.xml) are returned as plain text.
- Plain scripts (
- Verify table schemas referenced in the code using
@skill:discovering-gcp-data-assets.
- Identify the main file URI from metadata:
Root Cause Analysis (RCA) & Remediation:
- Correlate logs, stage metrics, and code logic.
- Pinpoint the exact failure cause and line number.
- Differentiate the root cause by environment — the same symptom has
different causes on each:
- Serverless Batches: dynamic-allocation memory limits, VPC / network egress restrictions, pre-installed PySpark dependency versions, and ephemeral driver/executor limits.
- Cluster Jobs: spot/preemptible VM eviction, YARN container memory bounds, local scratch-disk exhaustion, and master/worker machine sizing.
- For code-level refactoring, driver/executor OOM prevention, memory
spill mitigation, or partition layout optimizations, apply the Spark
optimization protocols: no terminal actions inside loops, no iterative
lineage chaining, no unbounded
.collect()/.toPandas()on the driver, native or vectorized (@pandas_udf) functions over row-wise Python UDFs, and.coalesce()rather than.repartition()when reducing partitions. The full catalog and the pre-submission refactoring protocol ship with thegcp-sparkskill, in itsreferences/spark_optimizations.mdandreferences/spark_refactoring_guide.md. - Propose concrete fixes (code optimizations, Spark tuning properties such
as
spark.driver.memoryorspark.sql.shuffle.partitions). - Check preconditions before recommending a setting. Do not advise
enabling AQE if
spark.sql.adaptive.enabledis already set, and do not advise Autotuning ifautotuning_enabledis already true. Read the batch's effective properties first. - Dataproc Serverless sizing constraints (validate any memory
recommendation against these):
- Default driver and executor memory is approximately 9.6 GB.
- Minimum memory per core is 1024m.
- Minimum is 4 cores per driver/executor.
- Write the RCA report yourself, following
references/rca_report_template.md; no script generates it.
Troubleshooting Scenarios Catalog
Refer to references/spark_log_patterns.md for full stack trace patterns and
remediation recipes:
- Driver vs. Executor OOM: Driver OOMs originate from
collect()ortoPandas(); Executor OOMs show exit code 137 or FetchFailedException. - Data Skew / Stragglers: Max task duration > 5x median duration with high
input skew. Fix with salting, AQE, or broadcast joins (size the threshold
from
scripts/spark_applications.py --action=sql --execution_id=<N>). - Schema & Type Errors:
NumberFormatException,BadRecordException. Fix with proper casting or PERMISSIVE read mode. - Serialization & Pickling:
cannot pickleclosures. Fix by initializing objects inside worker functions. - Python UDF Exceptions: Inspect
jsonPayload.messagefor Python traceback. Fix null handling. - File / Path Not Found & IAM:
PATH_NOT_FOUND, 403 Access Denied. Verify GCS path and storage permissions. - Dependency / Import Errors:
ModuleNotFoundError. Package dependencies with--py-filesor archives.
Important Constraints
- Read-Only First: Do NOT modify user code before proving the root cause with logs and metrics.
- No Hallucinations: If logs are empty, state so explicitly.
- Safety: Do not print plaintext secrets or credentials found in environment properties.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

