Skill: Dataflow Template Logical Error Debugging
Trigger
/smt-e2e-dataflow-debugging <FILE_NAME>.tfvars
Scope
This skill is STRICTLY restricted to testing the following templates:
gcs-spanner-dv
sourcedb-to-spanner
datastream-to-spanner
spanner-to-sourcedb
Goal
To debug logical errors and data discrepancies by comparing source data (e.g., Cloud SQL) with destination data (e.g., Spanner).
Prerequisites
- The Dataflow job must be able to launch and run to a terminal state (Succeeded, Failed) using the provided
.tfvars file. This skill is NOT for debugging startup/runtime crashes.
terraform CLI installed and configured.
gcloud CLI installed and authenticated (gcloud auth login).
mvn (Maven) and a compatible JDK installed.
git installed.
- Access to the source database (e.g., Cloud SQL) instance, database, and credentials.
- Access to the destination Spanner instance and database.
- Appropriate IAM permissions for Dataflow, Cloud SQL, Spanner, GCS, and Cloud Logging.
- Database client tools installed (e.g.,
psql, mysql client, or willingness to use gcloud sql connect).
Variables
<FILE_NAME>.tfvars: The Terraform variables file.
<YOUR_PROJECT_ID>: The target Google Cloud Project ID.
<YOUR_REGION>: The Google Cloud region for the Dataflow job.
<JOB_ID>: The Dataflow Job ID.
<JOB_NAME>: The name of the Dataflow job.
- Cloud SQL Connection Info (Extracted from .tfvars):
<CSQL_INSTANCE>: Cloud SQL instance name.
<CSQL_DATABASE>: Cloud SQL database name.
<CSQL_USER>: Cloud SQL username.
<CSQL_PASSWORD>: Cloud SQL password (if applicable).
<CSQL_PROJECT>: Project of the Cloud SQL instance.
- Spanner Connection Info (Extracted from .tfvars):
<SPANNER_INSTANCE>: Spanner instance name.
<SPANNER_DATABASE>: Spanner database name.
<SPANNER_PROJECT>: Project of the Spanner instance.
<MAVEN_MODULE_PATH>: The relative path to the template's maven module (e.g. v2/sourcedb-to-spanner).
<TEMPLATE_NAME>: The name of the template.
<YOUR_STAGING_BUCKET>: Cloud Storage bucket for staging.
Global Agent Rules
- Fail-Fast Protocol: If any executed terminal command returns an error or non-zero exit code, STOP IMMEDIATELY. Output the error to the user and ask for intervention. Do not attempt autonomous retries.
- Data Privacy: Ensure no real PII, credentials, or production connection details are exposed in logs or command outputs.
Workflow Phases
Phase 1: Deployment & Job Monitoring
- Deploy the Dataflow Job:
- Monitor Status: Wait for the job to reach a terminal state (Succeeded or Failed). Monitor status via Google Cloud Console or
gcloud.
Phase 2: Log Collection & Initial Analysis
- Retrieve Job IDs: Infer
<JOB_ID> and <JOB_NAME> from the Terraform output or by listing active jobs:gcloud dataflow jobs list --project=<YOUR_PROJECT_ID> --region=<YOUR_REGION>
- Inspect Job Logs: Retrieve job message logs to identify warnings or non-obvious issues:
gcloud logging read 'resource.type="dataflow_step" AND resource.labels.job_id="<JOB_ID>" AND logName=~"projects/.*/logs/dataflow.googleapis.com%2Fjob-message"' \
--project=<YOUR_PROJECT_ID> \
--limit=200 \
--format="table(timestamp, textPayload, severity)" --order=asc
- Inspect Worker Logs: Check worker execution logs for specific exceptions or stack traces:
gcloud logging read 'resource.type="dataflow_step" AND logName=~"projects/.*/logs/dataflow.googleapis.com%2Fworker" AND resource.labels.job_id="<JOB_ID>"' \
--project=<YOUR_PROJECT_ID> \
--limit=500 \
--format="table(timestamp, jsonPayload.message, severity)" --order=asc
Phase 3: Data Inspection & Validation
- Inspect Source Data (Cloud SQL): Connect to the Cloud SQL instance and query source tables:
# For PostgreSQL
gcloud sql connect <CSQL_INSTANCE> --user=<CSQL_USER> --project=<CSQL_PROJECT>
# For MySQL
gcloud sql connect <CSQL_INSTANCE> --user=<CSQL_USER> --project=<CSQL_PROJECT>
Execute validation queries:SELECT COUNT(*) FROM your_source_table;
SELECT * FROM your_source_table LIMIT 10;
- Inspect Destination Data (Spanner): Execute SQL queries on the destination Spanner database:
gcloud spanner databases execute-sql <SPANNER_DATABASE> \
--instance=<SPANNER_INSTANCE> \
--project=<SPANNER_PROJECT> \
--sql="SELECT COUNT(*) FROM your_destination_table"
gcloud spanner databases execute-sql <SPANNER_DATABASE> \
--instance=<SPANNER_INSTANCE> \
--project=<SPANNER_PROJECT> \
--sql="SELECT * FROM your_destination_table LIMIT 10"
Phase 4: Discrepancy Verification & Resolution
- Analyze Differences:
- Row Counts: Do source and destination row counts match?
- Schema Mapping: Are column types and names mapped correctly?
- Value Assertions: Check NULL values, string encoding, timestamps, and precision.
- Code Correction: Locate the transformation logic in the
.java files under the GoogleCloudPlatform/DataflowTemplates repository and fix the bug.
- Re-stage Template: Rebuild and upload the updated Flex Template:
mvn clean package -PtemplatesStage -DskipTests \
-DprojectId="<YOUR_PROJECT_ID>" \
-DbucketName="<YOUR_STAGING_BUCKET>" \
-DstagePrefix="templates" \
-DtemplateName="<TEMPLATE_NAME>" \
-pl <MAVEN_MODULE_PATH> -am
Phase 5: Re-testing & Iteration
- Clean Destination Table: Delete destination records to prepare for a clean run:
gcloud spanner databases execute-sql <SPANNER_DATABASE> \
--instance=<SPANNER_INSTANCE> \
--project=<SPANNER_PROJECT> \
--sql="DELETE FROM your_destination_table WHERE true"
- Re-run Job: Deploy the job again with the newly built template (Phase 1) and verify the fix.
Important Considerations
- Idempotency: Ensure clean test tables before re-running to avoid duplicate count errors.
- Data Volume: Limit queries to subsets when working with large volumes.
- Terraform State: Avoid modifying resources manually outside of Terraform to prevent state drift.
Source: GoogleCloudPlatform/DataflowTemplates — distributed by TomeVault.
1---2name: googlecloudplatform-dataflowtemplates-dataflowtemplates3description: Skill: Dataflow Template Logical Error Debugging4---56# Skill: Dataflow Template Logical Error Debugging78## Trigger9`/smt-e2e-dataflow-debugging <FILE_NAME>.tfvars`1011## Scope12This skill is **STRICTLY** restricted to testing the following templates:13* `gcs-spanner-dv`14* `sourcedb-to-spanner`15* `datastream-to-spanner`16* `spanner-to-sourcedb`1718## Goal19To debug logical errors and data discrepancies by comparing source data (e.g., Cloud SQL) with destination data (e.g., Spanner).2021## Prerequisites22* The Dataflow job must be able to launch and run to a terminal state (Succeeded, Failed) using the provided `.tfvars` file. This skill is NOT for debugging startup/runtime crashes.23* `terraform` CLI installed and configured.24* `gcloud` CLI installed and authenticated (`gcloud auth login`).25* `mvn` (Maven) and a compatible JDK installed.26* `git` installed.27* Access to the source database (e.g., Cloud SQL) instance, database, and credentials.28* Access to the destination Spanner instance and database.29* Appropriate IAM permissions for Dataflow, Cloud SQL, Spanner, GCS, and Cloud Logging.30* Database client tools installed (e.g., `psql`, `mysql` client, or willingness to use `gcloud sql connect`).3132## Variables33* `<FILE_NAME>.tfvars`: The Terraform variables file.34* `<YOUR_PROJECT_ID>`: The target Google Cloud Project ID.35* `<YOUR_REGION>`: The Google Cloud region for the Dataflow job.36* `<JOB_ID>`: The Dataflow Job ID.37* `<JOB_NAME>`: The name of the Dataflow job.38* **Cloud SQL Connection Info (Extracted from .tfvars):**39 * `<CSQL_INSTANCE>`: Cloud SQL instance name.40 * `<CSQL_DATABASE>`: Cloud SQL database name.41 * `<CSQL_USER>`: Cloud SQL username.42 * `<CSQL_PASSWORD>`: Cloud SQL password (if applicable).43 * `<CSQL_PROJECT>`: Project of the Cloud SQL instance.44* **Spanner Connection Info (Extracted from .tfvars):**45 * `<SPANNER_INSTANCE>`: Spanner instance name.46 * `<SPANNER_DATABASE>`: Spanner database name.47 * `<SPANNER_PROJECT>`: Project of the Spanner instance.48* `<MAVEN_MODULE_PATH>`: The relative path to the template's maven module (e.g. `v2/sourcedb-to-spanner`).49* `<TEMPLATE_NAME>`: The name of the template.50* `<YOUR_STAGING_BUCKET>`: Cloud Storage bucket for staging.5152## Global Agent Rules53* **Fail-Fast Protocol**: If any executed terminal command returns an error or non-zero exit code, STOP IMMEDIATELY. Output the error to the user and ask for intervention. Do not attempt autonomous retries.54* **Data Privacy**: Ensure no real PII, credentials, or production connection details are exposed in logs or command outputs.5556## Workflow Phases5758### Phase 1: Deployment & Job Monitoring591. **Deploy the Dataflow Job**:60 * Navigate to the directory containing `<FILE_NAME>.tfvars`.61 * Initialize Terraform:62 ```bash63 terraform init64 ```65 * Launch the job:66 ```bash67 terraform apply --var-file=<FILE_NAME>.tfvars -auto-approve68 ```692. **Monitor Status**: Wait for the job to reach a terminal state (Succeeded or Failed). Monitor status via Google Cloud Console or `gcloud`.7071### Phase 2: Log Collection & Initial Analysis721. **Retrieve Job IDs**: Infer `<JOB_ID>` and `<JOB_NAME>` from the Terraform output or by listing active jobs:73 ```bash74 gcloud dataflow jobs list --project=<YOUR_PROJECT_ID> --region=<YOUR_REGION>75 ```762. **Inspect Job Logs**: Retrieve job message logs to identify warnings or non-obvious issues:77 ```bash78 gcloud logging read 'resource.type="dataflow_step" AND resource.labels.job_id="<JOB_ID>" AND logName=~"projects/.*/logs/dataflow.googleapis.com%2Fjob-message"' \79 --project=<YOUR_PROJECT_ID> \80 --limit=200 \81 --format="table(timestamp, textPayload, severity)" --order=asc82 ```833. **Inspect Worker Logs**: Check worker execution logs for specific exceptions or stack traces:84 ```bash85 gcloud logging read 'resource.type="dataflow_step" AND logName=~"projects/.*/logs/dataflow.googleapis.com%2Fworker" AND resource.labels.job_id="<JOB_ID>"' \86 --project=<YOUR_PROJECT_ID> \87 --limit=500 \88 --format="table(timestamp, jsonPayload.message, severity)" --order=asc89 ```9091### Phase 3: Data Inspection & Validation921. **Inspect Source Data (Cloud SQL)**: Connect to the Cloud SQL instance and query source tables:93 ```bash94 # For PostgreSQL95 gcloud sql connect <CSQL_INSTANCE> --user=<CSQL_USER> --project=<CSQL_PROJECT>96 # For MySQL97 gcloud sql connect <CSQL_INSTANCE> --user=<CSQL_USER> --project=<CSQL_PROJECT>98 ```99 Execute validation queries:100 ```sql101 SELECT COUNT(*) FROM your_source_table;102 SELECT * FROM your_source_table LIMIT 10;103 ```1042. **Inspect Destination Data (Spanner)**: Execute SQL queries on the destination Spanner database:105 ```bash106 gcloud spanner databases execute-sql <SPANNER_DATABASE> \107 --instance=<SPANNER_INSTANCE> \108 --project=<SPANNER_PROJECT> \109 --sql="SELECT COUNT(*) FROM your_destination_table"110111 gcloud spanner databases execute-sql <SPANNER_DATABASE> \112 --instance=<SPANNER_INSTANCE> \113 --project=<SPANNER_PROJECT> \114 --sql="SELECT * FROM your_destination_table LIMIT 10"115 ```116117### Phase 4: Discrepancy Verification & Resolution1181. **Analyze Differences**:119 * **Row Counts**: Do source and destination row counts match?120 * **Schema Mapping**: Are column types and names mapped correctly?121 * **Value Assertions**: Check NULL values, string encoding, timestamps, and precision.1222. **Code Correction**: Locate the transformation logic in the `.java` files under the `GoogleCloudPlatform/DataflowTemplates` repository and fix the bug.1233. **Re-stage Template**: Rebuild and upload the updated Flex Template:124 ```bash125 mvn clean package -PtemplatesStage -DskipTests \126 -DprojectId="<YOUR_PROJECT_ID>" \127 -DbucketName="<YOUR_STAGING_BUCKET>" \128 -DstagePrefix="templates" \129 -DtemplateName="<TEMPLATE_NAME>" \130 -pl <MAVEN_MODULE_PATH> -am131 ```132133### Phase 5: Re-testing & Iteration1341. **Clean Destination Table**: Delete destination records to prepare for a clean run:135 ```bash136 gcloud spanner databases execute-sql <SPANNER_DATABASE> \137 --instance=<SPANNER_INSTANCE> \138 --project=<SPANNER_PROJECT> \139 --sql="DELETE FROM your_destination_table WHERE true"140 ```1412. **Re-run Job**: Deploy the job again with the newly built template (Phase 1) and verify the fix.142143## Important Considerations144* **Idempotency**: Ensure clean test tables before re-running to avoid duplicate count errors.145* **Data Volume**: Limit queries to subsets when working with large volumes.146* **Terraform State**: Avoid modifying resources manually outside of Terraform to prevent state drift.147148---149> Source: [GoogleCloudPlatform/DataflowTemplates](https://github.com/GoogleCloudPlatform/DataflowTemplates) — distributed by [TomeVault](https://tomevault.io).150<!-- tomevault:4.0:skill_md:2026-07-03 -->