What you will be able to do
- Use COPY_HISTORY, VALIDATION_MODE and VALIDATE_PIPE_LOAD to find out why files partially loaded or failed to load
- Use SYSTEM$PIPE_STATUS to tell a cloud notification problem apart from a path mismatch or a paused pipe
- Fix common Snowpipe causes: a deleted SNS subscription, a missing GCS Monitoring Viewer role, PATTERN filters, pipe load metadata, overlapping pipes and a broken storage integration link
Key concept
Load activity history (COPY_HISTORY) — Every bulk COPY and every Snowpipe load is recorded with a status for each file and the first error it hit. Start troubleshooting here. Whatever the history shows, or fails to show, tells you which tool to use next.
1.Start with the load history
Snowflake documents the same method for bulk loads and for Snowpipe: first, query the load activity history for the target table. COPY_HISTORY reports a STATUS for each set of files: loaded, partially loaded or failed. When a load partially loaded or failed, the FIRST_ERROR_MESSAGE column gives the reason. As the name says, that column holds only the first error found in a file. A file with ten bad rows still shows one message.
There are two versions of this history, and they differ in ways that matter during an incident. The COPY_HISTORY view in the ACCOUNT_USAGE schema, which also backs the account-level Copy History page in Snowsight, covers 365 days for every table in the account. Its latency is up to two hours. The COPY_HISTORY table function, which backs the table-level Copy History tab, covers only 14 days for one table but has very low latency. Both include bulk COPY INTO statements, pipe loads and files loaded through the web interface. In Snowsight you can filter by status (In progress, Loaded, Failed, Partially loaded, Skipped) and hover over a Failed entry to see the error details.
Permissions affect what you see. The table function needs the MONITOR privilege on the account, or USAGE on the database and schema plus any privilege on the table. Without MONITOR on the pipe, pipe details are masked as NULL. Don't mistake that for a load that didn't use a pipe.
Checkpoint 1 of 7· Check yourself
A load into one table failed ten minutes ago. You want its error as soon as possible. Which source should you query?
The table-level function has very low latency. The account-level view can lag by up to two hours, so a load from ten minutes ago may not appear there yet.
“The table-level data loading activity has very low latency”Source: docs.snowflake.com
2.Seeing every error, not just the first
Because FIRST_ERROR_MESSAGE stops at one error, the next step is to run a COPY statement with VALIDATION_MODE set to RETURN_ALL_ERRORS. Point it at the same files you tried to load. The statement validates the data and returns the errors without loading anything, so you can run it safely against production tables.
The documented pattern goes one step further and turns the error list into a file you can fix. It captures the validation query's ID, reads the rejected records back through RESULT_SCAN, and unloads them to a stage. These statements must run one after another in the same session, because LAST_QUERY_ID returns the ID of the query that ran just before it.
For files that Snowpipe tried to load, the same validation applies: run COPY INTO <table> with RETURN_ALL_ERRORS against those files. The Snowpipe troubleshooting guide also points to the VALIDATE_PIPE_LOAD function for validating data files after a pipe load hits errors.
COPY INTO mytable
FROM @mystage/myfile.csv.gz
VALIDATION_MODE=RETURN_ALL_ERRORS;
SET qid=last_query_id();
COPY INTO @mystage/errors/load_errors.txt FROM (SELECT rejected_record FROM TABLE(result_scan($qid)));Checkpoint 2 of 7· Fill the gap
Which value makes this COPY report every error in the file without loading data?
COPY INTO mytable
FROM @mystage/myfile.csv.gz
VALIDATION_MODE= ? ;RETURN_ALL_ERRORS is the validation option the troubleshooting guide uses. CONTINUE, SKIP_FILE and ABORT_STATEMENT are ON_ERROR behaviours, not validation modes.
Source: docs.snowflake.comCheckpoint 3 of 7· Exam question
A data engineer runs a `COPY INTO` statement against 50 staged CSV files without specifying `VALIDATION_MODE`. The load must keep processing even when individual rows are malformed, and after it finishes the engineer needs to know how many rows were rejected from each file. Which approach satisfies both requirements?
Correct answer: A — Set `ON_ERROR = CONTINUE` in the COPY statement, then compare the `ROWS_PARSED` and `ROWS_LOADED` columns returned by the COPY command to calculate how many rows were rejected per file.
- A. This is correct. `ON_ERROR = CONTINUE` loads every row it can parse and skips the bad ones rather than stopping, and the COPY command's result set includes `ROWS_PARSED` and `ROWS_LOADED` per file, so the difference tells you exactly how many rows were rejected.
- B. `SKIP_FILE` discards an entire file once any error is found, which throws away rows that would otherwise have loaded, so it does not satisfy "keep processing malformed rows." `VALIDATION_MODE` also never loads data, so it cannot recover row counts from a skipped file.
- C. `ABORT_STATEMENT` rolls back the whole file's load as soon as one error appears, so no rows persist for that file at all; there is nothing partial for `LOAD_HISTORY` to report, which defeats the continue-processing requirement.
- D. The bulk-load default for `ON_ERROR` is `ABORT_STATEMENT`, not a continue-on-error mode, so omitting the option does not meet the requirement. `SYSTEM$PIPE_STATUS` also reports pipe state for Snowpipe, not row-level results for a manual COPY statement.
3.When auto-ingest loads nothing: reading the pipe status
With auto-ingest Snowpipe, the load history may be empty because no event ever reached the pipe. SYSTEM$PIPE_STATUS returns the pipe's state as JSON. Each field points to a different part of the event chain.
| Field | What it tells you | Likely cause / next step |
|---|---|---|
| lastReceivedMessageTimestamp | Last event message received from the message queue | Empty or older than expected: check the Amazon SQS/SNS or Azure Event Grid configuration, or the service itself |
| lastForwardedMessageTimestamp | Last create-object message with a matching path forwarded to the pipe | Messages received but not forwarded: the storage path doesn't match the stage path plus pipe path |
| executionState | Execution state of the pipe, e.g. PAUSED | Paused: the pipe owner resumes it with ALTER PIPE |
| error | Detail when the pipe has trouble starting | Read it when executionState shows a start-up problem |
The path check catches many people out. The path in the pipe definition is appended to the path in the stage definition, so the effective location is the two combined. Only messages triggered by created objects are consumed. If messages are both received and forwarded, the problem is in the data, so go back to COPY_HISTORY.
Several causes are specific to one cloud:
- Amazon SNS. The first pipe that references an SNS topic subscribes a Snowflake-owned SQS queue to that topic. If an AWS administrator deletes the subscription, every pipe on that topic stops receiving S3 events. To fix it, wait 72 hours for SNS to clear the deleted subscription, then recreate the pipes with CREATE OR REPLACE PIPE on the same topic. To skip the wait, create a topic with a different name and recreate the pipes against that topic instead. - Google Cloud Storage. Only one staged file's event is read, or loads are delayed by minutes to a day or more. The usual cause is that the Snowflake service account was never granted the Monitoring Viewer role. - Azure ADLS Gen2. Some third-party clients don't call FlushWithClose, and that call is what triggers the event. Call the REST API manually. - Snowpipe REST API. The endpoints use key pair authentication with a JWT. A request without a token returns error 400. An invalid token returns 401 with "JWT token is invalid".
Instead of polling, you can have Snowpipe push error notifications to the cloud messaging service where your account is hosted (there is no cross-cloud support). These notifications only fire when ON_ERROR is SKIP_FILE, which is the default. NOTIFICATION_HISTORY shows what was sent.
Checkpoint 4 of 7· Check yourself
SYSTEM$PIPE_STATUS shows a recent lastReceivedMessageTimestamp, but lastForwardedMessageTimestamp is stale. What is the most likely cause?
Messages are arriving, so the notification service works. They are not being forwarded because their path doesn't match the combined stage and pipe path.
“there is likely a mismatch between the blob storage path where the new data files are created and the combined path”Source: docs.snowflake.com
Checkpoint 5 of 7· Match them up
Match each symptom to its documented resolution
Tap a term, then the definition that fits it.
Each of these failures sits in the notification or authentication layer, not in the data, so validating the files would not find them.
“In general, either issue is caused when a GCS administrator has not granted the Snowflake service account the Monitoring Viewer role.”Source: docs.snowflake.com
4.Files skipped, files duplicated, and broken stage links
Sometimes the pipe works but particular files are missing or loaded twice. Each case has a documented cause.
Expected files missing from COPY_HISTORY. Query an earlier time window. If the files duplicated earlier ones, the history may have recorded them when the originals were attempted. Also check the pipe's COPY statement for a PATTERN clause whose regular expression filters out every staged file. Changing PATTERN means recreating the pipe with CREATE OR REPLACE PIPE.
A subset of files never loaded. Run ALTER PIPE … REFRESH. This is the fix when the external stage was previously used for bulk COPY, when files were already in the stage before event notifications were set up, or when a notification failure stopped files from being queued.
Fixed files that still won't load. Snowpipe's load metadata belongs to the pipe, not the table. A staged file with the same name as one already loaded is ignored even if its contents changed (a different eTag). Files that failed during the pipe's COPY are still registered in that metadata, and later pipe activity, including REFRESH, skips them. Load those files manually with a COPY statement. TRUNCATE TABLE does not clear this metadata.
Duplicated rows. Run SHOW PIPES and compare the COPY statements. If two pipes reference overlapping paths such as <storage_location>/path1/ and <storage_location>/path1/path2/, files staged in the deeper path are loaded by both pipes.
Error 003139, "Integration … cannot be found". A stage links to its storage integration through a hidden ID, not the integration's name. CREATE OR REPLACE STORAGE INTEGRATION drops the integration and recreates it with a new ID, which breaks every stage linked to it. Re-link each stage with ALTER STAGE … SET STORAGE_INTEGRATION.
Load timestamps that look too early. A column defaulting to CURRENT_TIMESTAMP is evaluated when the load is compiled, not when it commits, so its values come before COPY_HISTORY's LOAD_TIME. Use METADATA$START_SCAN_TIME instead.
Checkpoint 6 of 7· Check yourself
A file failed in a pipe because of bad content. You fix it, re-upload it under the same name, and run ALTER PIPE … REFRESH. It still doesn't load. What should you do?
Failed files stay registered in the pipe's metadata, and REFRESH ignores them. Truncating the table doesn't clear pipe metadata. A manual COPY is the documented fix.
“You can use a COPY statement to load the skipped files manually.”Source: docs.snowflake.com
Checkpoint 7 of 7· Check yourself
After an administrator ran CREATE OR REPLACE STORAGE INTEGRATION, loads from an external stage fail with error 003139. What resolves it?
The stage was linked to the old integration's hidden ID. Recreating the integration again would assign yet another ID, so each stage has to be re-linked explicitly.
“you must reestablish the association between each stage and the storage integration by executing ALTER STAGE stage_name SET STORAGE_INTEGRATION = storage_integration_name”Source: docs.snowflake.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Truncating the target table lets Snowpipe reload files it already processed.Why is that wrong?
Snowpipe's file-loading metadata belongs to the pipe, not the table, so TRUNCATE TABLE leaves it in place and those file names are still ignored.
Covered in Files skipped, files duplicated, and broken stage links
2.Setting ON_ERROR=CONTINUE on a pipe still sends you error notifications for the rows it skips.Why is that wrong?
Error notifications only work with ON_ERROR=SKIP_FILE, the default. With CONTINUE, Snowpipe sends none.
Covered in When auto-ingest loads nothing: reading the pipe status
3.After someone deletes the SQS subscription to the SNS topic, recreating the pipes right away restores S3 events on the same topic.Why is that wrong?
You have to wait 72 hours for SNS to clear the deleted subscription before recreating pipes on that topic. The alternative is a topic with a new name.
Covered in When auto-ingest loads nothing: reading the pipe status
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“The FIRST_ERROR_MESSAGE column provides a reason when an attempt partially loaded or failed.”
↩︎ Start with the load history“Note that if a set of files has multiple issues, the FIRST_ERROR_MESSAGE column only indicates the first error encountered.”
↩︎ Seeing every error, not just the first“A stage links to a storage integration using a hidden ID rather than the name of the storage integration.”
↩︎ Files skipped, files duplicated, and broken stage links“It is recommended to include and query METADATA$START_SCAN_TIME instead”
↩︎ Files skipped, files duplicated, and broken stage links“The STATUS column indicates whether a particular set of files was loaded, partially loaded, or failed to load.”
↩︎ Key concept“No data is loaded when this copy option is specified.”
↩︎ Prediction“you must reestablish the association between each stage and the storage integration by executing ALTER STAGE stage_name SET STORAGE_INTEGRATION = storage_integration_name”
↩︎ Checkpoint - 2.
“The account-level data loading activity has a latency of up to 2 hours”
↩︎ Start with the load history“If you use a role that does not have the MONITOR privilege on the pipe, pipe details are masked as NULL.”
↩︎ Start with the load history“The table-level data loading activity has very low latency”
↩︎ Checkpoint - 3.
“To validate the data files, query the VALIDATE_PIPE_LOAD function.”
↩︎ Seeing every error, not just the first“Note that a path specified in the pipe definition is appended to any path in the stage definition.”
↩︎ When auto-ingest loads nothing: reading the pipe status“To modify the PATTERN value, it is necessary to recreate the pipe using the CREATE OR REPLACE PIPE syntax.”
↩︎ Files skipped, files duplicated, and broken stage links“Truncating the table by using the TRUNCATE TABLE command doesn’t delete the Snowpipe file-loading metadata.”
↩︎ Exam trap 1“Wait 72 hours from the time when the SNS topic subscription was deleted.”
↩︎ Exam trap 3“there is likely a mismatch between the blob storage path where the new data files are created and the combined path”
↩︎ Checkpoint“In general, either issue is caused when a GCS administrator has not granted the Snowflake service account the Monitoring Viewer role.”
↩︎ Checkpoint“You can use a COPY statement to load the skipped files manually.”
↩︎ Checkpoint - 4.
“Currently, cross-cloud support is not available for push notifications.”
↩︎ When auto-ingest loads nothing: reading the pipe status“Snowpipe will not send any error notifications if the ON_ERROR copy option is set to CONTINUE.”
↩︎ Exam trap 2