File Connector

Load CSV (and TSV or TXT delimited text), JSON, NDJSON, XML, Parquet and Excel files — plain, gzipped or zipped — into Snowflake from an SFTP server, an Amazon S3 bucket, a Windows or NAS share, or a folder on a machine in your network. Files are read in place: nothing on the source is copied, moved, renamed or deleted.

Setup at a glance

  1. Create a connection to where the files are, and press Test Connection.
  2. Add a file set for each table you want: which folder, which files, which format.
  3. Create the pipeline: pick the destination, tick the file sets, save.
  4. Choose how each task syncs: Full, or Incremental with Replace, Upsert or Append.
  5. Sync and check the run's Files view.

Each step is covered below, followed by reference details and troubleshooting.

Choose your source

Your files are on…Pick this connectorNeeds a hybrid agent?
An SFTP serverSFTP (files on a remote server) Only if the server is on a private network or allows listed IPs only
An Amazon S3 bucket, or S3-compatible storage (Cloudflare R2, MinIO, Wasabi, Google Cloud Storage with HMAC keys) Amazon S3 (and S3-compatible storage) Only if the bucket or store is reachable from your network alone
A Windows or NAS share, \\server\shareNetwork Share (SMB) Yes
A folder on the machine where the agent runs (local disk or a share mounted there) Folder on the Agent Machine Yes

A hybrid agent runs inside your network, so the files and the credentials never leave it; only the rows you load reach Snowflake. Direct means Elglide's cloud connects to the source itself, with nothing to install.

Step 1 — Create the connection

Go to Connections → Add and pick the connector from Connector Category. Fill in the fields for your source below, then press Test Connection. A good test reads “✓ Found N file(s) in M folder(s) under …” and names the place it actually read; that is the quickest proof that everything after this step will work.

Create Connection runs the same test and saves only when it passes. If the source is briefly unreachable, Save Anyway saves it untested. Passwords, keys and secrets are write-only: once saved they are never shown again, and leaving the box blank when you edit keeps the saved one.

SFTP server

FieldWhat to enter
ConnectivityDirect (default) when the server is reachable from the internet. Hybrid agent when it has a private address (10.x, 172.16–31.x, 192.168.x, an internal name) or only accepts listed source IPs.
Host, PortThe server's name or IP address, and its port (usually 22).
UsernameThe account to sign in as. Elglide reads only what that account can read.
MethodPassword, SSH key (OpenSSH or PEM, with its Key Passphrase if it is encrypted), or SSH key + password for servers that require both. Password also covers servers that only accept keyboard-interactive sign-in.
Host Key FingerprintOptional but recommended. Leave it blank for the first test, which shows the server's SHA256:… fingerprint, then paste it in. From then on a server presenting a different key is refused.
Base pathThe folder every file set starts from, e.g. /exports. Blank means the account's home folder.
Direct connections do not come from a fixed IP address yet. If your server only accepts listed source IPs, use Hybrid agent for now — see IP allowlist. Direct also refuses a private or internal address, and Test Connection says so.

Amazon S3 bucket

FieldWhat to enter
ConnectivityDirect (default) for a normal AWS bucket. Hybrid agent when the bucket policy only admits your own network, or the store is only reachable from inside it.
BucketThe bucket name only — no s3:// and no path.
RegionThe bucket's region, e.g. eu-west-1. Blank means us-east-1.
PrefixThe folder inside the bucket every file set starts from, e.g. exports/daily. Blank means the top of the bucket.
EndpointBlank for Amazon S3. For an S3-compatible store, its full URL, e.g. https://storage.googleapis.com.
MethodAccess key (Access key ID + Secret access key) or IAM role (Role ARN, below — Direct only).

The identity only needs to list the bucket and read objects. A minimal policy for one prefix:

{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::your-bucket",
      "Condition": { "StringLike": { "s3:prefix": "exports/daily/*" } } },
    { "Effect": "Allow", "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket/exports/daily/*" }
  ]
}

Signing in with an IAM role (no stored keys)

  1. Choose IAM role as the Method. The form shows Elglide's Principal and your account's External ID.
  2. In AWS, create a role whose trust policy admits that Principal with that External ID:
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": { "AWS": "<Principal shown on the form>" },
        "Action": "sts:AssumeRole",
        "Condition": { "StringEquals": { "sts:ExternalId": "<External ID shown on the form>" } }
      }]
    }
  3. Attach the list-and-read policy above to the role, and paste its ARN into Role ARN.

The External ID is fixed for your account, so another Elglide customer who learns your role's ARN still cannot use it. An IAM role works with Direct only; through a hybrid agent, use an access key.

Windows or NAS share (SMB)

No mounting and no agent configuration: type the share and an account, and the agent you pick opens it.

FieldWhat to enter
ShareThe path as you would type it in Explorer: \\fileserver\exports. The part after the server must be a share the server publishes, not a folder inside one.
FolderOptional. A folder inside the share that every file set starts from, e.g. sales. Blank means the top of the share.
Username, DomainThe account to sign in as. Put the domain in Domain, not DOMAIN\user in Username. Leave Domain blank for a NAS with local accounts.
PasswordThat account's password.
Agent groupThe agent that opens the share. It must reach the server on port 445.
The share is opened with NTLM sign-in. A server that has NTLM switched off and requires Kerberos (common on domain-joined Windows servers) refuses it, and Test Connection says so. For that server, mount the share on the agent's machine and use a Folder on the Agent Machine connection instead.

Folder on the Agent Machine

The connection itself only needs a Name (a label, e.g. Finance exports) and the Agent group. Which folder it reads is set on the agent's machine, by whoever installed the agent — deliberately not in the portal, so nobody signed in can point it at an arbitrary path.

The quickest start: the agent bundle comes with FILE_ROOT=./files. Create a files folder next to the bundle's agent.sh, put your files in it, and Test Connection will list them. The agent only ever reads from it.

Using a different folder

Set FILE_ROOT in the bundle's .env, then stop and start the agent:

FILE_ROOT=/srv/exports          # Linux / macOS
FILE_ROOT=C:\Elglide\files      # Windows: a real folder on this PC

./agent.sh stop && ./agent.sh start
Use stop, then start — not docker compose restart, which leaves the file reader running against the old folder, so your change seems to do nothing.

A network share mounted on the agent's machine

Most shares are easier as a Network Share (SMB) connection. Mount one on the agent's machine only when its server requires Kerberos.

  • Linux: mount the share with /etc/fstab or a systemd unit (so it survives a reboot) and point FILE_ROOT at it. Mount several shares under one parent folder and point FILE_ROOT at the parent: each share becomes a subfolder you can pick per file set.
  • Windows: let Docker mount the share. In docker-compose.connectors.yml, uncomment the file-share volume and swap the volumes: line for the commented one; set FILE_SHARE_USER and FILE_SHARE_PASSWORD in .env. These stay on your machine.
  • Kubernetes: there is no .env; point the elglide-source-files PersistentVolumeClaim at your storage.
On Windows, never set FILE_ROOT to a mapped drive letter (Z:\) or a UNC path. Docker cannot see drive mappings, so it quietly mounts an empty folder; a UNC path is rejected. Test Connection catches this: it reports an empty folder instead of your files.

Step 2 — Add file sets

A file set says which files make one table. Open the connection, and in its File Sets list press + (Add a file set). Add one file set per destination table; a connection can have as many as you like.

FieldWhat to enter
NameBecomes the table name: daily_orders loads into DAILY_ORDERS.
GroupOptional. Groups file sets in the pipeline, the way a schema groups tables.
SubfolderWhere to look, relative to the connection's base path, prefix, share folder or the agent's folder. Blank means that folder itself.
Include subfoldersLook into nested folders too. Your pattern must also reach them — see below.
Pattern styleGlob (sales_*.csv) or Regex (^sales_\d{4}-\d{2}\.csv$). Applies to both pattern boxes.
Include patternsOne per line. A file matching any of them is selected.
Exclude patternsOptional. A file matching any of them is skipped, e.g. *.tmp.
Modified afterOptional. Ignore older files, even ones never loaded — the “start from here” filter for a folder with years of history.
Size rangeOptional. A minimum of 1 skips empty placeholder files.
File formatCSV / TSV / TXT, JSON, NDJSON, XML, Parquet or Excel. A file whose extension does not fit the format fails the run instead of being guessed at.
First line is a headerUntick when the first line is already data; columns are then named column_1, column_2, …
Format optionsOptional JSON, e.g. {"Delimiter":"\t"}. Required for XML. See Format options.
EncodingLeave as Connection default (UTF-8) unless the files say otherwise.
Changed filesAre appended to (on by default): a file that only grew is read from where the last read stopped. Untick if your exporter rewrites files. See Files that grow.

Patterns that work

You wantInclude pattern
Every CSV in the subfolder*.csv
Every CSV, including in nested folders (tick Include subfolders)**/*.csv
One export family, e.g. sales_2026-10-24.csvsales_*.csv
Two filename shapes into one tableorders_*.csv and legacy_orders_*.csv on two lines
Gzipped or zipped files*.csv.gz, *.zip
A tab-separated .txt export (format CSV, options {"Delimiter":"\t"})*.txt
* matches within one folder and stops at a /, so *.csv never reaches a nested folder even with Include subfolders ticked. **/ matches any number of folders, including none: **/*.csv finds sales.csv and 2026/q1/sales.csv. ? matches one character. Patterns are case-sensitive and use / on every system, including Windows.

Press Preview before saving: it lists exactly the files the patterns select, read live from the source, and warns when nothing matches.

Step 3 — Create the pipeline

  1. Open the connection's Pipelines tab and choose the Snowflake destination in Select destination….
  2. Under Schema Map, set the Snowflake schema the tables go into (it starts as FILES).
  3. Tick the file sets to load, and press Save. Each ticked file set becomes a task, loading one table.
  4. Optional: pick a Default Schedule. Manual only means a task runs when you press Sync.

Columns and types are detected from the newest files. Review them on a task's Schema tab, and press Refresh after the files' layout changes. A detected type is a proposal; it never overwrites a type you saved.

Step 4 — Choose how each task syncs

On a task, open Settings → Sync Mode. Pick Full or Incremental first:

  • Full — every run reads every matching file and rebuilds the table in one transaction. The table always equals the folder; the only choice that removes rows of files that were deleted.
  • Incremental (default) — every run reads only files that are new or changed since the last run, then the sync mode below decides what a changed file does to its earlier rows.
Sync modePick it whenA changed file…Key?
Replace (default) Each file is a complete batch (a daily export, a file per customer) that may be regenerated with corrections. Its earlier rows are removed and it is loaded again. No duplicates.No
Upsert Files carry updates to records that may already be loaded (an order number, a SKU). Rows with a matching key are updated, others inserted. Rows missing from the new version stay. Yes
Append Files only grow (logs) or are never rewritten once dropped. The cheapest mode. Is loaded again alongside the old rows (a duplicate, by design). A file that only grew has just its new rows read. No

Example

orders_mon.csv (orders 1–3) and orders_tue.csv (orders 4–5) are loaded: five rows. Before the next run, orders_wed.csv arrives with orders 6–7, orders_tue.csv is regenerated with order 4 corrected and order 5 removed, and orders_mon.csv is deleted.

Rows afterOrder 4Order 5Monday's rows
Replace6once, correctedgonekept
Upsert7once, correctedkeptkept
Append8twice — old and newkeptkept
Full3once, correctedgonegone

Safety built in

  • A load that fails part-way rolls back; the table keeps its previous rows.
  • A Full run never empties a table because a folder is empty: if no file matches, the run fails and the table is untouched.
  • A Full task skips the run when nothing in the folder changed, so a frequent schedule over a quiet folder costs nothing.
  • Upsert refuses a row with an empty key, rather than inserting a duplicate on every run.
  • Switching a task from Append to Replace leaves earlier rows alone; they are replaced as each file is next read. To start a table over, use Sync → Full Sync.

Step 5 — Sync and check

Press Sync on a task. When it finishes, open the run in Sync History and choose Files to see every file it read, with its size, modified time, row count and why it was read (new, changed, grown, or full).

Every loaded table also gets four columns that trace each row back to its file:

ColumnContains
_ELGLIDE_FILEThe file's path relative to the subfolder; for a zip, the member: orders.zip!2026-09/orders.csv
_ELGLIDE_LINEThe record's number within that file
_ELGLIDE_FILE_MODIFIEDThe file's last-modified time
_ELGLIDE_EXTRACTED_ATWhen the sync ran

JSON and NDJSON tables also get _ELGLIDE_RAW, the whole record as VARIANT, unless the file set's KeepRaw option is false.

How Elglide knows what is new

After a successful load, each file is remembered by its path, size and modified time; the next run skips it without opening it. A file with a new size or modified time is read again, and the sync mode decides what happens to its earlier rows. Nothing is remembered until the load commits, so a failed run simply picks the same files up next time.

  • A file edited in place that keeps both its size and its timestamp looks unchanged. Some copy tools preserve timestamps; if yours does, write a new filename instead.
  • A file deleted from the folder is not noticed by Incremental tasks: its rows stay. Only a Full task removes them.
  • A file re-added under a new name is new work and loads again.
  • To read everything again, use Sync → Full Sync.

Files that grow

A log or a running export is often appended to in place. With Changed files → Are appended to ticked, a file that grew is checked first: if its earlier contents are unchanged, only the new rows are read, and _ELGLIDE_LINE continues from the last number. If the earlier part changed, the whole file is read, as for any changed file.

Only Append saves the work: Replace and Full exist to replace a file's earlier rows, so they always read whole files, and compressed files are always read whole.

Format options

Optional JSON in the file set's Format options box. Leave it blank for the defaults — except XML, which must name its record element.

FormatOptionDefault and use
CSV / TSV / TXTDelimiter, — use "\t" for tab, "|" for pipe, ";" for semicolon
Quote"
Escape"
NullSequencenone — e.g. "\\N" to load that text as NULL
HasHeadertrue — same as the First line is a header box
SkipHeaderLines0 — lines dropped before the header (banners, preambles)
SkipFooterLines0 — lines dropped at the end (totals, trailers)
JSON / NDJSONRecordPaththe root array
FlattenDepth2 — how many levels of nested objects become columns; 0 keeps each object whole as VARIANT
Separator_ — joins nested names, so customer.email lands as customer_email
KeepRawtrue — adds the whole record as VARIANT in _ELGLIDE_RAW
XMLRecordElementRequired. The path to the element that is one row, e.g. {"RecordElement":"/Orders/Order"}. Without it every run fails.
AttributesFlatten (each attribute becomes a column) or Ignore
KeepNamespacePrefixfalse — <ns:Order> lands as Order
FlattenDepth2 — as for JSON
Separator_ — as for JSON
ParquetNo options — the file describes itself.
ExcelSheetNamethe first visible sheet, e.g. {"SheetName":"Orders"}
HasHeadertrue
SkipHeaderLines0 — rows dropped above the header (report titles)
SkipFooterLines0 — rows dropped at the end (totals)

The CSV format reads .csv, .tsv, .txt and .tab files; set the Delimiter for anything not comma-separated.

Excel workbooks

  • A file set reads one sheet of each .xlsx or .xls workbook. To load two sheets, add two file sets.
  • Macro-enabled .xlsm and binary .xlsb workbooks are not read.
  • Formulas load the value last saved in the workbook. Merged cells load their value in the first cell only.
  • Blank rows after the data are ignored; a blank row between data rows loads as NULLs.

The run stops and names the sheet and cell for an error cell (#N/A, #REF!, #DIV/0!), a value under a column with no header, or a password-protected workbook.

Compressed files

Gzip and zip files are read in place on every kind of source; nothing needs unpacking first.

  • gzip (orders.csv.gz): one file; the name under .gz tells the format.
  • zip: every member is read as the file set's format. _ELGLIDE_FILE names the member, e.g. orders.zip!2026-09/orders.csv.
  • A zip must hold only files of that format. __MACOSX/, .DS_Store and Thumbs.db are ignored; use an exclude pattern such as *.pdf to skip anything else.
  • Archives inside archives, tar, bz2 and PGP files are not read.

When the files' columns change

Before loading, every file is checked against the task's saved columns. What happens next is set in the task's schema evolution settings: by default a new column is added to the table and a vanished column stops the run, naming the file and the column.

  • CSV and Excel with a header are matched by column name, so reordered columns are fine.
  • CSV and Excel without a header are matched by position, so any added or removed column stops the run.
  • JSON, NDJSON, XML and Parquet are matched by name; a record missing a field gets NULL.

Run limits

A file set can carry per-run caps. The connector's defaults suit almost everyone; when a cap applies:

  • Files per run and Bytes per run: files beyond the cap wait for the next run. A Full run ignores these, since a partial rebuild would lose rows.
  • Rows per file written: rows per file uploaded to Snowflake.

Troubleshooting

You seeWhat to do
Test Connection: found no files on a Folder connection Check FILE_ROOT in the agent's .env points at a real folder that holds files (never a mapped drive letter), then stop and start the agent.
A run: No files match this file set Press Preview on the file set. For files in nested folders, use **/*.csv and tick Include subfolders. Check the subfolder name and the case of the pattern.
Folder '…' does not exist The file set's Subfolder is wrong, or relative to the wrong base path.
… is a private or internal address (SFTP, S3) A Direct connection points at something only your network can reach. Switch to Hybrid agent.
SFTP: Could not connect to host:port Check host and port. If the server only admits listed IPs, use Hybrid agent.
SFTP: … refused the credentials Check username and password or key; an encrypted key also needs its passphrase.
SFTP: … presented a different host key If the server was rebuilt, paste the new fingerprint the message shows. Otherwise you may not be reaching the server you think — check before re-pinning.
S3: the bucket does not exist / different region Bucket name only (no s3://); set Region to the bucket's region; check Endpoint for S3-compatible stores.
S3: access key not recognised / secret does not match Check both values and that the key is active. A secret access key is 40 characters.
S3: access denied / could not assume the role Grant s3:ListBucket and s3:GetObject; for a role, the trust policy must match the Principal and External ID on the form exactly.
Share: Could not reach … on port 445 Check the server name and that the agent's network allows SMB to it.
Share: has no share called … The name after the server is the share itself; put any folder inside it in Folder.
Share: rejected the credentials for … Check username, domain and password, with the domain in Domain.
Share: refused the sign-in method The server requires Kerberos. Mount the share on the agent's machine and use a Folder connection.
… does not look like a CSV file naming archive.zip!member The zip holds a file of another kind. Add an exclude pattern for it.
A column is missing or new See When the files' columns change; press Refresh on the Schema tab and save to accept the new layout.
A value will not load Nothing was committed. Fix the file and sync again; it is picked up automatically.
Excel: an error cell or locked workbook Fix or clear the named cell, or save the workbook without a password.
Loading from a database instead? See Hybrid Deployment Mode and the sync modes reference.