Snowflake MigrationClickHouse Workshops

Troubleshooting

A symptom, cause, and fix reference for failures learners hit while running this lab, grouped by where they surface.

Every entry below is a real failure: the eleven documented in the lab's own part READMEs, plus five caught while building and testing this workshop. Find your symptom, read the cause, apply the fix. If nothing here matches, the instructor track's ## Common failures sections cover the facilitator side of each module in more depth, and your Solutions Architect is the next stop.

Toolchain and setup

dbt fails with a mashumaro import error, or will not install

  • Symptom - installing dbt-snowflake or dbt-clickhouse fails, or dbt raises an import error mentioning mashumaro that has nothing obviously to do with your Python version.
  • Cause - dbt-snowflake and dbt-clickhouse both require Python 3.11, 3.12, or 3.13. Python 3.14+ breaks their shared mashumaro dependency, and the failure usually surfaces in an unrelated module after the mistake was already made.
  • Fix - install 3.13 alongside your system Python (for example brew install python@3.13) and rebuild the virtualenv with that interpreter explicitly: python3.13 -m venv .venv.

The Snowflake source environment

terraform init fails with a provider error

  • Symptom - terraform init in workshop_public/snowflake_migration_lab/01-setup-snowflake/ fails while resolving a provider.
  • Cause - an old Terraform binary or no network access to the Terraform registry.
  • Fix - use Terraform >= 1.6 and confirm internet access to the registry.

snowsql connection refused

  • Symptom - snowsql -a ${SNOWFLAKE_ORG}-${SNOWFLAKE_ACCOUNT} -u ${SNOWFLAKE_USER} refuses the connection.
  • Cause - SNOWFLAKE_ORG or SNOWFLAKE_ACCOUNT is wrong.
  • Fix - re-check both values against the account you created, then retry the same snowsql command.

dbt run fails with relation not found

  • Symptom - dbt run in the Part 1 dbt project reports a relation that does not exist.
  • Cause - the database structure was never created.
  • Fix - run ./setup.sh --skip-seed first, and confirm profiles.yml points at NYC_TAXI_DB.

Superset shows connection refused

  • Symptom - the Part 1 Superset UI refuses the connection right after docker-compose up.
  • Cause - Superset takes about 60 seconds to initialize.
  • Fix - wait 60 seconds and retry. If it still fails, check docker logs nyc_taxi_superset.

Data seed takes longer than expected

  • Symptom - the seed step in workshop_public/snowflake_migration_lab/01-setup-snowflake/ seems stuck.
  • Cause - this is normal Snowflake behavior at this scale, not a hang. The TABLE(GENERATOR) insert that produces 50M rows takes roughly 10-12 minutes, and the follow-up UPDATE that populates the VARIANT TRIP_METADATA column on all 50M rows takes another 15-20 minutes on a SMALL warehouse.
  • Fix - let it run. Neither step is interactive; there is nothing to retry.

Provisioning ClickHouse Cloud and migrating the data

Terraform auth fails with 401 Unauthorized

  • Symptom - the Terraform apply in workshop_public/snowflake_migration_lab/03-migrate-to-clickhouse/ fails with 401 Unauthorized.
  • Cause - CLICKHOUSE_TOKEN_KEY or CLICKHOUSE_TOKEN_SECRET is wrong, or the key lacks the required scope.
  • Fix - regenerate the key pair from the ClickHouse Cloud UI under Settings -> API keys, and make sure it has Admin scope.

Migration script fails mid-run

  • Symptom - scripts/02_migrate_trips.py dies partway through the 50M-row copy.

  • Cause - transient network or warehouse hiccups during a long-running transfer.

  • Fix - re-run with --resume. The script watermarks on max(pickup_at) already present in ClickHouse and skips rows it has already loaded:

    python scripts/02_migrate_trips.py --resume

Migration script connection error

  • Symptom - the migration script cannot reach Snowflake or ClickHouse.

  • Cause - one or more Snowflake or ClickHouse environment variables are unset in the current shell.

  • Fix - check them, then re-source the state files before retrying:

    echo $SNOWFLAKE_ORG $SNOWFLAKE_ACCOUNT $SNOWFLAKE_USER $SNOWFLAKE_PASSWORD
    echo $CLICKHOUSE_HOST $CLICKHOUSE_PASSWORD

    Run source .env && source .clickhouse_state first, then retry.

dbt run fails with Connection refused or Unknown host

  • Symptom - dbt run against the ClickHouse project fails to resolve or connect to a host.
  • Cause - CLICKHOUSE_HOST is not set in the current shell.
  • Fix - source .clickhouse_state from the module directory, then retry dbt run.

dbt fails with Could not find profile named 'nyc_taxi_ch'

  • Symptom - dbt debug or dbt run in workshop_public/snowflake_migration_lab/03-migrate-to-clickhouse/dbt/nyc_taxi_dbt_ch fails immediately with a missing-profile error.
  • Cause - the ClickHouse dbt profile was never added to ~/.dbt/profiles.yml.
  • Fix - open workshop_public/snowflake_migration_lab/03-migrate-to-clickhouse/dbt/nyc_taxi_dbt_ch/profiles.yml.example and merge its nyc_taxi_ch: block into your existing ~/.dbt/profiles.yml as a second top-level profile. Do not overwrite the file - doing so deletes the nyc_taxi: profile from module 01 and breaks its Step 4 refresh loop. See 03 Provision and migrate, which covers this merge step in full.

dbt on ClickHouse

analytics.agg_hourly_zone_trips is empty after the dbt run

  • Symptom - after module 04's dbt run, analytics.agg_hourly_zone_trips has zero rows, and any dashboard chart backed by it shows no data.
  • Cause - this is expected, not a failure. The model's incremental filter is WHERE pickup_at >= now() - INTERVAL 2 HOUR, which only matches rows written by the live trip producer. All rows moved by the migration script are historical, so none of them fall inside that 2-hour window.
  • Fix - nothing to fix. Zero is the correct value here. The table fills once the producer is writing directly into ClickHouse after 05 Benchmark and cutover's cutover step.

Dashboards and benchmark

Superset shows 403 Forbidden

  • Symptom - the Superset UI returns 403 Forbidden partway through the module.
  • Cause - the session cookie expired.
  • Fix - log out, log back in at http://localhost:8088, then re-run bash superset/add_clickhouse_connection.sh.

Benchmark shows N/A for Q7

  • Symptom - run_benchmark.sh's output CSV has N/A in place of a speedup value for query 7.
  • Cause - the benchmark script could not connect to ClickHouse.
  • Fix - confirm CLICKHOUSE_HOST is set (source .clickhouse_state) and the service is running, then re-run the benchmark.

An imported Superset dashboard will not connect to ClickHouse

  • Symptom - dashboards imported into Superset load, but their charts cannot reach ClickHouse.
  • Cause - the committed export ZIP has its host redacted to your-instance.clickhouse.cloud. add_clickhouse_connection.sh patches the real URI in from .env before importing; a manual import through the Superset UI does not.
  • Fix - use bash superset/add_clickhouse_connection.sh instead of a manual import, or edit the connection afterward to use your real CLICKHOUSE_HOST and credentials.

Cutover and parity

The parity check fails, or the cutover appears to lose rows

  • Symptom - module 05's row-count parity check fails, or the cutover looks like it dropped data.

  • Cause - the --resume catch-up pass was skipped. The Snowflake producer writes continuously through modules 01-05, so module 03's migration only captured a prefix of the data; the tail exists only in Snowflake until it is caught up. Stopping the Snowflake producer early (for example, right after module 01) silently destroys this module's cutover demonstration, since there is then no tail left to catch up.

  • Fix - run the catch-up pass before checking parity. It moves only the gap rows and takes seconds to minutes, not the original 40-50:

    python scripts/02_migrate_trips.py --resume
    bash scripts/01_verify_migration.sh

On this page