File

9 min read • 1,853 words
Connect File with Amfelt: setup, required privileges, configuration reference, and type mapping.

Available v1.10.5 Released October 31, 2026

Overview  

The File connector extracts data from CSV, Parquet, and flat JSONL files as a source. It reads a single file per connection, derives the logical object name from the file name, and hands the records to the agent as Arrow record batches — Parquet schemas are read from the file’s own metadata, while CSV and JSONL schemas are inferred from the data.

Typical uses are one-off historical loads, reference data maintained as files, and exports from systems that have no direct connector yet. The file must be reachable from the Amfelt agent’s file system (a local path or a mounted share).

Capabilities  

FeatureSourceTarget
Full load —
Incremental load——
Change Data Capture (CDC)——
Schema drift —

Prerequisites  

Before connecting a file source:

  • File access from the Amfelt agent: the file must exist on the agent’s file system (a local path or a mounted network share) and be readable by the agent process.
  • A supported format: CSV (with a header row), Parquet, or flat JSONL: one JSON object per line, with scalar values only. Nested objects and arrays are not read yet. The format is resolved from the file extension, or set explicitly with a ?format= query parameter on the connection path.
  • Stable encoding: CSV and JSON files are read as UTF-8. A UTF-8 byte-order mark at the start of the file, as Excel’s “CSV UTF-8” export writes, is skipped.

Connect  

  1. In Amfelt, add a file source and select the File connector.
  2. Provide the connection properties (see Configuration reference): the file’s absolute path on the agent’s machine and its format (csv, parquet, or json for JSONL).
  3. Validate the connection and choose Discover schema — the logical object takes its name from the file name (for example /data/customers.csv becomes customers).

A connection resolves to an ODCS server descriptor like:

servers:
  - server: files-drop
    type: local
    path: /data/customers.csv
    format: csv

Schema Handling  

  • Parquet files carry their own typed schema; it is used as-is.
  • CSV and JSON schemas are inferred from every row of the file when metadata is ingested. On a typed target such as PostgreSQL, deploying creates the columns with those types; DuckDB stores every column as text (VARCHAR). A column whose values do not all share one type is inferred as text and loads every value exactly as written; cast it downstream or switch the export to Parquet for fully typed extraction.
  • Ingestion never infers a column as a number when any of its values would change as one: a leading zero (007, -01), an integer beyond the 64-bit range, or a decimal with more digits than a double holds. Such a column, typically zip codes, account numbers or long identifiers, is inferred as text and keeps its exact text. A difference in form only, such as 1.10 for 1.1 or 1e3 for 1000, still loads as a number.
  • On a typed target such as PostgreSQL, a deployed column keeps its type: deploying again under the same schema prefix does not change the type of a column that already exists. If a later version of the file holds values that a deployed column’s type cannot hold exactly, such as a zip code with a leading zero in a column deployed as a number, re-ingest the file’s metadata and deploy it under a new schema prefix before you load that file.
  • Because ingestion infers a CSV or JSON schema from every row, it reads the whole file on the agent’s machine, so its time grows with the file’s size, and a file of a few gigabytes can take minutes. The agent stops metadata ingestion that runs longer than its import timeout, 2 minutes by default, and the ingestion fails. To ingest a larger file, set the agent’s AMFELT_IMPORT_TIMEOUT environment variable to a longer duration, such as 10m or 1h, and restart the agent. A Parquet file carries its own typed schema, so ingestion does not infer one from its rows.
  • Validating the connection reads only the header and the first 4,096 rows, so it stays fast on a large file; it reports the number of columns, not their types.
  • Each run reads the file’s schema again when it starts, then reads the rows. If the file changes in between, so that a value no longer fits the type the run read, the run stops at that row and names the column and the row. That value is not loaded, and staging keeps the rows loaded before it. From agent v4.18.3 on, the run then skips the history, bridge and business layers, so they keep what the last successful run loaded. An earlier agent still runs the history layer over the partial staging.

Sync Modes  

ModeWhat it does
Full loadReloads all selected data on every run.

Configuration Reference  

PropertyTypeRequiredDescription
formatstringYesThe format of the file(s)
pathstringYesThe relative or absolute path to the data file(s).

Troubleshooting  

The path is resolved on the Amfelt agent’s file system, not the control plane’s. Verify the file exists on the machine running the agent and that any network share is mounted before the agent starts.
The connection test refuses a relative path, because it would resolve against the agent’s working directory rather than a fixed location. Give the file’s full path on the agent’s machine, such as /data/customers.csv.
The agent process needs read permission on the file and traverse permission on every directory in the path.
The format is resolved from the file extension. For files with a non-standard extension, set it explicitly with a ?format=csv, ?format=parquet, or ?format=json (for JSONL) query parameter on the connection path.
CSV and JSON schemas are inferred from every row of the file when metadata is ingested. A column whose values do not share one type, or that holds a value a number would change (a leading zero, an integer beyond 64 bits, a decimal with more digits than a double holds), is inferred as text and loads exactly as written. Cast it downstream, or switch the export to Parquet, which carries its own typed schema.
CSV and JSON schemas are inferred from every row, so ingesting a CSV or JSON file reads the whole file on the agent’s machine, and a large file takes longer. The agent stops metadata ingestion that runs longer than its import timeout, 2 minutes by default, and the ingestion fails. Set the agent’s AMFELT_IMPORT_TIMEOUT environment variable to a longer duration, such as 10m or 1h, restart the agent, and run the ingestion again. A Parquet export avoids the inference, because it carries its own typed schema.
On a typed target such as PostgreSQL, a deployed column keeps the type it was inferred with, and deploying again under the same schema prefix does not change an existing column. If the file now holds values that type cannot hold exactly, for example zip codes with a leading zero in a column deployed as a number, re-ingest the file’s metadata and deploy it under a new schema prefix before you load that file. DuckDB stores every column as text, so this does not arise there.
A run reads the file’s schema when it starts, then reads the rows. If the file is rewritten in between so that a value no longer fits the type the run read, the run stops at that row and names the column and the row. That value is not loaded, and staging keeps the rows loaded before it. From agent v4.18.3 on, history and the later layers keep what the last successful run loaded. Let whatever writes the file finish before the run starts. If the new values no longer fit the deployed column types, follow the previous entry before running again; otherwise run again.

Changelog  

Release history for the File connector, newest first.

Features

  • Keep the state schema and the file ledger

Features

  • Publish plugin releases on the connectors repo

Bug Fixes

  • Move connector module paths to github.com/amfeltlabs

Features

  • Open PostgreSQL with pgx; core v3.41.2, plugin-sdk v5.17.4

Features

  • Write the amf_ metadata columns and name Amfelt in what connectors ship

Bug Fixes

  • Bump golang.org/x/net to v0.60.0 (GO-2026-6617)

Features

  • Ship third-party notices in postgres and file archives

Bug Fixes

  • Say that ingesting a CSV or JSON file reads the whole file

Bug Fixes

  • Skip a leading UTF-8 byte-order mark in CSV and JSONL files

Bug Fixes

  • Never load a CSV or JSON value altered by type inference

Features

  • Record third-party marks per connector

Features

  • Compare scope in the postgres and duckdb templates

Features

  • answer the source connection test on plugin-sdk v5.12.2

Features

  • Postgres and duckdb sources answer the source connection test

Bug Fixes

  • Read a header-only csv as an empty table instead of panicking

Bug Fixes

  • Require plugin-sdk v5.9.3 so a read-only-default role is not reported ok

Features

  • Pass the declared override surface to the renderer (ADR-117)
  • Declare the override surface and govern the declared tier (ADR-117)

Bug Fixes

  • Select the modules that consume a changed module

Features

  • Bind the readers to their catalog pages

Features

  • Add the source connector

Breaking Changes

  • Newconnector generator, docbundle gate, file docbundle

Breaking Changes

  • Adopt plugin-sdk /v5 — re-pin, ctx seams, quoting, BaseRenderer, DTOs

Features

  • Add JSONL file-format reader (inference + dispatch)

Features

  • Parquet reader and multi-format file dispatch

Features

  • Per-property target DDL typer (durable B4b, CSV renders distinct columns)

Features

  • Source-file CSV connector (proven CSV to postgres)

Licensing  

Third-party open-source packages bundled by this connector, with their licenses. Attribution only: informational, not an evaluation of the connector.

PackageLicense
github.com/Masterminds/semver  MIT
github.com/andybalholm/brotli  BSD-3-Clause AND MIT
github.com/apache/arrow-go/v18  Apache-2.0 AND BSD-3-Clause
github.com/apache/thrift  Apache-2.0 AND BSD-3-Clause AND GNU-All-permissive-Copying-License
github.com/bmatcuk/doublestar/v4  MIT
github.com/cespare/xxhash/v2  MIT
github.com/fsnotify/fsnotify  BSD-3-Clause
github.com/gabriel-vasile/mimetype  MIT
github.com/go-playground/locales  MIT
github.com/go-playground/universal-translator  MIT
github.com/go-playground/validator/v10  MIT
github.com/go-viper/mapstructure/v2  MIT
github.com/goccy/go-json  MIT
github.com/goccy/go-yaml  MIT
github.com/google/flatbuffers  Apache-2.0
github.com/google/uuid  BSD-3-Clause
github.com/hashicorp/errwrap  MPL-2.0
github.com/hashicorp/go-multierror  MPL-2.0
github.com/iancoleman/strcase  MIT
github.com/jinzhu/copier  MIT
github.com/klauspost/compress  Apache-2.0 AND BSD-3-Clause AND MIT
github.com/klauspost/cpuid/v2  MIT
github.com/leodido/go-urn  MIT
github.com/lmittmann/tint  MIT
github.com/mattn/go-isatty  MIT
github.com/mitchellh/go-wordwrap  MIT
github.com/pelletier/go-toml/v2  MIT
github.com/pierrec/lz4/v4  BSD-3-Clause
github.com/sagikazarmark/locafero  MIT
github.com/santhosh-tekuri/jsonschema/v6  Apache-2.0
github.com/spf13/afero  Apache-2.0
github.com/spf13/cast  MIT
github.com/spf13/cobra  Apache-2.0
github.com/spf13/pflag  BSD-3-Clause
github.com/spf13/viper  MIT
github.com/subosito/gotenv  MIT
github.com/zeebo/xxh3  BSD-2-Clause
go.yaml.in/yaml/v3  MIT
golang.org/x/crypto  BSD-3-Clause
golang.org/x/exp  BSD-3-Clause
golang.org/x/net  BSD-3-Clause
golang.org/x/sync  BSD-3-Clause
golang.org/x/sys  BSD-3-Clause
golang.org/x/text  BSD-3-Clause
google.golang.org/genproto/googleapis/rpc  Apache-2.0
google.golang.org/grpc  Apache-2.0
google.golang.org/protobuf  BSD-3-Clause