agentleFS
Google CloudKnown publisherGoogleCloudPlatform/data-agent-kit-plugin/skills/gcp-spark-troubleshooting/SKILL.md

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

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
  1. Very specific:

    When given a GCS URI (gs://...

    line 37
  2. Very specific:

    When asked to troubleshoot a standard cluster job (e.g.

    line 40
  3. Very specific:

    When asked to troubleshoot a Dataproc Serverless batch or session (e.g.

    line 44
  4. Distinctive:

    Every diagnosis draws on three evidence sources: logs (what failed),

    line 99
  5. Very specific:

    Stages are returned: use them, even if stateMessage or the logs already name an error.

    line 145
  6. Very specific:

    Before reporting that stage data is unavailable or that a job "ran no stages", quote the scripts/spark_applications.py output that shows it.

    line 157
  7. Very specific:

    Use --session_id for a session and --project if it differs from the active gcloud project.

    line 195
  8. Very specific:

    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 …

    line 220
  9. Distinctive:

    Follow this strict 6-step process.

    line 238
  10. Very specific:

    Confirm the target is reachable: before planning around it.

    line 260
  11. Very specific:

    If project or region is not specified, read the active gcloud configuration (gcloud config list).

    line 270
  12. Very specific:

    Quick Win: Check stateMessage or status.details immediately for quick diagnosis of errors (e.g.

    line 277
  13. Very specific:

    Logs: use gcloud logging read with filter resource.type="cloud_dataproc_batch" AND resource.labels.batch_id="<BATCH_ID>".

    line 284
  14. Very specific:

    Spark application data: run python3 scripts/spark_applications.py --batch_id=<BATCH_ID> --region=<REGION> --action=summary (or …

    line 296
  15. Very specific:

    Path B: Cluster Jobs: Read driverOutputResourceUri using scripts/spark_gcs_log_reader.py --action=tail --lines=100.

    line 304
  16. Distinctive:

    not: start searching local files or Dataform workspaces for a cluster job.

    line 310
  17. Very specific:

    Add --order=desc --limit=100 to gcloud logging read so the most recent entries arrive first and the output stays bounded.

    line 315
  18. Very specific:

    Run scripts/spark_stage_diagnostics.py with --batch_id or --session_id (it fetches every stage, with task quantiles, plus the executor …

    line 324
  19. Very specific:

    Add --format=json to get the Data Worker Agent's output shape (status PASS/FAIL/ERROR, errorMessage, violations, stageMetrics, summary), …

    line 378
  20. Very specific:

    Plain scripts (.py, .scala, .java, .sql): run --uri=gs://bucket/scripts/job.py to print the numbered source.

    line 404
  21. Very specific:

    Archives (.jar, .zip) — overview: run --uri without --entry to get the Main-Class from MANIFEST.MF, the package and class inventory, …

    line 406
  22. Very specific:

    Verify table schemas referenced in the code using @skill:discovering-gcp-data-assets.

    line 425
  23. Very specific:

    Check preconditions before recommending a setting: Do not advise enabling AQE if spark.sql.adaptive.enabled is already set, and do not …

    line 452
  24. Distinctive:

    Default driver and executor memory is approximately 9.6 GB.

    line 458
  25. Very specific:

    Write the RCA report yourself, following references/rca_report_template.md.

    line 461
  26. Distinctive:

    Read-Only First: Do NOT modify user code before proving the root cause with logs and metrics.

    line 491
  27. Distinctive:

    No Hallucinations: If logs are empty, state so explicitly.

    line 493
  28. Distinctive:

    Safety: Do not print plaintext secrets or credentials found in environment properties.

    line 494

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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://... or https://storage.googleapis.com/...) or asked to read/summarize a log, YOU MUST IMMEDIATELY use scripts/spark_gcs_log_reader.py.
  • When asked to troubleshoot a standard cluster job (e.g. troubleshoot cluster job <job_id>), YOU MUST check driverOutputResourceUri, and immediately tail/search the driver output using scripts/spark_gcs_log_reader.py with --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: inspect stateMessage, then gather all three evidence sources for Serverless (logs, Spark application data, code) before concluding. Serverless stage data comes from the sparkApplications API through scripts/spark_applications.py; it does not depend on a Persistent History Server, spark.eventLog.dir, or Cloud Logging. An empty sparkHistoryServerConfig, no event log in GCS, or empty Cloud Logging results never show that stage data is unavailable; only scripts/spark_applications.py itself can show that.
  • NEVER cat, gcloud storage cat, or text-decode a .jar, .zip, or .class file — they are binary and will render as unreadable output. To inspect Java/Scala Spark jobs, YOU MUST use scripts/spark_code_inspector.py, which disassembles compiled bytecode into readable JVM assembly.
  • NEVER point scripts/spark_code_inspector.py at 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. Use scripts/spark_gcs_log_reader.py for 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 gcloud CLI.
    • spark_applications.py and spark_stage_diagnostics.py call the Dataproc REST API with a token from gcloud auth print-access-token. If that token is rejected (HTTP 401, for example ACCESS_TOKEN_TYPE_UNSUPPORTED under context-aware access), they retry automatically with gcloud auth application-default print-access-token. If both fail, the fix is gcloud auth application-default login.
  • Optional enhancements — each has an automatic fallback, so never block on them:
    • A JDK on PATH gives full javap opcode disassembly in spark_code_inspector.py. Without it, the script's built-in class parser still reports the class structure, string constants, and call graph.
    • Reading .zst event logs uses the standard library compression.zstd module on Python 3.14+. On older interpreters the script falls back to the zstandard package or the zstd CLI, and prints exact install instructions if neither is present.

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. stateMessage from describe. 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 with scripts/spark_gcs_log_reader.py.
  • Spark application data: scripts/spark_applications.py --action=summary, then --action=stages; rules with scripts/spark_stage_diagnostics.py. Served by the sparkApplications API: no History Server or event log needed, and available after the workload ends.
  • Code: pysparkBatch.mainPythonFileUri or sparkBatch.mainJarFileUri, with scripts/spark_code_inspector.py.

Dataproc cluster job

  • Logs: driverOutputResourceUri with scripts/spark_gcs_log_reader.py; Cloud Logging (cloud_dataproc_job) as a fallback.
  • Spark application data: the Spark event log under spark.eventLog.dir, with scripts/spark_gcs_log_reader.py --action=summarize_events.
  • Code: pysparkJob.mainPythonFileUri or the job's JAR, with scripts/spark_code_inspector.py.

Direct GCS URI

  • Logs: scripts/spark_gcs_log_reader.py.
  • Spark application data: --action=summarize_events if 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 stateMessage or 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 stateMessage are 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=info first; 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=100 for the final exception.
  • Search: --action=search --regex=<re> (or --substring) with --ignore_case; --context and --max_matches bound the output. If a search returns zero matches, retry with --ignore_case before 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=summary

Use --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 the data size of each exchange. Use it to recommend spark.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: reports Main-Class and the class inventory. Start here for Java and Scala jobs.
  • --entry=<class> (for example com.example.MySparkJob, or the app.jar!/com/example/MySparkJob.class form): disassembles the class, including inner classes and Scala closures (--no_inner_classes to 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.

  1. Tooling & Environment Verification:

    • Verify the gcloud CLI is present and authenticated via gcloud 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 returns 403, 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 in scripts/ depend only on the standard library, so no pip install is 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 .zst decoder 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.
  2. 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".
    • Quick Win: Check stateMessage or status.details immediately for quick diagnosis of errors (e.g. OutOfMemoryError, PATH_NOT_FOUND).
  3. Log Retrieval & Evidence Gathering:

    • Path A: Serverless Batches & Sessions (logs + Spark application data; see Evidence Flow by Workload Type):
      • Logs: use gcloud logging read with filter resource.type="cloud_dataproc_batch" AND resource.labels.batch_id="<BATCH_ID>". Start with severity>=ERROR. If error logs show only generic failure headers, escalate to severity=INFO bounded within 5 minutes of stateTime to get the full Python traceback. Inspect both jsonPayload.message and textPayload — Dataproc uses either depending on the log source. If Cloud Logging returns nothing, read the driver output at <runtimeInfo.outputUri>.000000000 with scripts/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 (see Dataproc Serverless: how to read the Spark application data).
    • Path B: Cluster Jobs: Read driverOutputResourceUri using scripts/spark_gcs_log_reader.py --action=tail --lines=100.
      • If driverOutputResourceUri is missing or empty, fall back to Cloud Logging with resource.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.
    • Path C: Direct GCS URI: For files > 20 MB or event logs, use scripts/spark_gcs_log_reader.py.

    Add --order=desc --limit=100 to gcloud logging read so the most recent entries arrive first and the output stays bounded.

  4. Stage Metrics & Rule-Based Diagnostics:

    • Applies to Dataproc Serverless batches and sessions whose scripts/spark_applications.py summary 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.py with --batch_id or --session_id (it fetches every stage, with task quantiles, plus the executor summary through the sparkApplications API, exactly as the Dataproc Data Worker Agent does), or with --telemetry_file for 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) and total_executor_summary. Each record is a flat dict keyed by the snake_case proto field path, for example s["stage_metrics.jvm_gc_time_millis"] or s["task_quantile_metrics.duration_millis.percentile_50"]:
      • a rule that reads s is 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.md has the field reference, the language rules, example rules for common Spark issues, and patterns for correlating signals.
    • 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, '', [], {} or None (timestamps), so no None checks are needed on numbers. Use ratio(a, b) for ratios: it yields 0.0 for a zero denominator, whereas / raises and skips the rule. s["status"] is a string such as 'STAGE_STATUS_FAILED', and *_time fields are datetimes. 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. Set detail (an f-string works well) so that each finding quotes the measured value. Give ratio rules a magnitude floor (for example executor_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=json to get the Data Worker Agent's output shape (status PASS/FAIL/ERROR, errorMessage, violations, stageMetrics, summary), plus warnings for 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). See Spark Applications Workflow above.
  5. 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) and sparkBatch.mainClass (e.g. com.example.MySparkJob).
    • 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.py to print the numbered source.
      • Archives (.jar, .zip) — overview: run --uri without --entry to get the Main-Class from MANIFEST.MF, the package and class inventory, and the key top-level entries.
      • Archives — targeted entry: pass --entry with 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.class is also accepted.
      • Compiled .class entries are disassembled into readable JVM assembly via javap, 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_classes to suppress them on very large classes.
      • Non-.class archive entries (MANIFEST.MF, .properties, .xml) are returned as plain text.
    • Verify table schemas referenced in the code using @skill:discovering-gcp-data-assets.
  6. 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 the gcp-spark skill, in its references/spark_optimizations.md and references/spark_refactoring_guide.md.
    • Propose concrete fixes (code optimizations, Spark tuning properties such as spark.driver.memory or spark.sql.shuffle.partitions).
    • Check preconditions before recommending a setting. Do not advise enabling AQE if spark.sql.adaptive.enabled is already set, and do not advise Autotuning if autotuning_enabled is 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() or toPandas(); 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 pickle closures. Fix by initializing objects inside worker functions.
  • Python UDF Exceptions: Inspect jsonPayload.message for 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-files or 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.