Troubleshooting¶
Status: Available in ETLantic 0.53.0 (Beta release candidate).
Quickstart stuck?¶
| Symptom | Fix |
|---|---|
Docs version is newer than etlantic --version |
python -m pip install 'etlantic==0.53.0' (pin plugins to the same version) |
etlantic init refuses a non-empty directory |
Create an empty subdirectory, then cd into it before init |
etlantic: command not found |
Prefer python -m etlantic … so the active interpreter is used |
Run succeeds but data/out.json has no Ada/Grace |
Seed files under data/ are required; re-check the Quickstart JSON seeds and the same --profile |
Full install/PATH detail: Installed version is older and Wrong interpreter.
pip install etlantic rejects my Python version¶
ETLantic requires Python 3.11 or newer. Check with:
Installed version is older than the docs¶
These docs describe ETLantic 0.53.0. Confirm what you installed:
Until you have the docs train version, upgrade from PyPI:
python -m pip uninstall -y etlantic
python -m pip install 'etlantic==0.53.0'
python -m etlantic --version # expect 0.53.0
Or accept compatible 0.49.x patches within the minor:
From a checkout, prefer uv sync / git pull. See
Installation.
Wrong interpreter or etlantic: command not found¶
The console script is on PATH only for the environment where you installed ETLantic. Prefer the module form tied to the active interpreter:
If that fails with No module named etlantic, reinstall into the intended
virtualenv. If import etlantic works but etlantic on PATH does not, you
are mixing environments.
CLI validate/plan unexpectedly runs my pipeline¶
etlantic loads path.py:Class by importing the module. Keep contracts and
pipeline classes at module scope, but put seed/run side effects under
if __name__ == "__main__" so import is safe. See
Quickstart.
Plugin install fails (etlantic-polars, etlantic-pyspark, …)¶
Those packages ship with ETLantic 0.53.0 as separate distributions. Keep every plugin on the same minor as core.
From PyPI:
python -m pip install --upgrade \
'etlantic-polars==0.53.0' 'etlantic-pandas==0.53.0'
python -m pip install --upgrade \
'etlantic-sql==0.53.0' 'etlantic-pyspark==0.53.0'
python -m pip install --upgrade \
'etlantic-airflow==0.53.0' 'etlantic-prefect==0.53.0'
python -m pip install --upgrade \
'medallantic==0.53.0'
From a checkout:
uv sync --group dataframes # polars + pandas
uv sync --group sql
uv sync --group pyspark
uv sync --group airflow
uv sync --group prefect
uv sync --group medallantic
uv sync --group keyring
uv sync --group sqlmodel
Confirm Python is 3.11+ and the package name uses a hyphen
(etlantic-pyspark), not an underscore.
Core and plugin versions do not match¶
Compare distributions in the same interpreter:
python -c "import importlib.metadata as m; print(m.version('etlantic')); print(m.version('etlantic-polars'))"
Core 0.53.x requires official plugins from the same minor
(0.49.x). Do not mix plugins from a different minor with core (for example
0.25 plugins with 0.26 core). Remove stale plugin
versions and install matching pins, for example:
Use the plugin distribution relevant to your engine in place of
etlantic-polars.
A transformation has no implementation¶
Declaring a Transformation defines its contract, not its executable code.
Either register a native implementation:
…or use a shipped portable relational compiler: Polars and PySpark shipped in
0.13, and eager Pandas shipped in 0.14. Author with
@MyTransformation.portable, install the matching engine plugin, and select
that engine with portable_transform_policy="require". See
examples/portable_polars_kernel.py for the Polars path.
Portable compiler not discovered / PMXFORM302¶
python -m etlantic plugin list --profile development --format json
python -m pip show etlantic etlantic-polars
If no transform compiler appears for Polars, install a matching
etlantic-polars==0.53.0 into the same environment as core. Entry-point
discovery uses installed distribution metadata, so reinstall the plugin after
editable-install or interpreter changes.
PMXFORM301 unsupported action or function¶
PMXFORM301 means the selected compiler does not support an action, function,
or profile required by that particular plan. In 0.17, relational joins are
graduated across the shipped portable relational compilers, while advanced
window and reshape families are graduated on Polars and PySpark. Conversion
support remains capability-specific. Check the selected plugin's advertised
capabilities; narrow the portable definition, choose a capable engine, add a
native @implementation(...), or use
portable_transform_policy="prefer" / "native".
Diagnostic codes → remediation¶
| Code | Meaning | Fix |
|---|---|---|
PMCFG100 |
Unknown bare profile name | Use a built-in template, a JSON path, or --allow-adhoc-profile |
PMCFG110 / PMCFG111 |
Legacy bindings-only profile |
Prefer assets; etlantic profile migrate or --accept-legacy-bindings once |
PMPLUG401 |
Production plugin_allowlist is empty |
Set a non-empty allowlist (see prod.example.json); do not use bare --profile production for CI |
PMPLUG402 |
Plugin name/version not permitted by allowlist | Add the package with a matching pin, or install the allowlisted version |
PMPLUG403 |
Allowlist pin is not a valid version specifier | Fix the pin syntax (==0.53.0, >=0.53.0,<0.54, …) |
PMXFORM301 |
Portable action unsupported on selected compiler | Narrow portable IR, switch engine, or add @implementation |
PMEXEC410 |
Report persistence failed after publication | Inspect terminal status; recover orphaned writes; do not assume success |
PMEXEC416 |
Missing callable reader on storage binding | Register a reader or use a supported binding |
PMEXEC501 |
Unsafe retry after partial write | Fix write mode / idempotency; keep PMORCH310 compile checks in CI |
PMORCH310 |
Compile-time unsafe retry/orchestration claim | Adjust orchestration/write semantics before deploy |
| Fingerprint mismatch | Plan digest does not match payload | Regenerate plan after upgrade; do not hand-edit fingerprints |
Missing wire schema |
Plan/report lacks etlantic.plan/1 (etc.) |
Regenerate with current CLI/SDK; do not strip schema |
Full catalog: Diagnostics.
Production validation fails with PMPLUG401¶
The built-in production profile intentionally has an empty plugin allowlist
and fails closed. Create an explicit production Profile JSON with a non-empty
plugin_allowlist containing exact trusted plugin versions such as
"etlantic-polars": "==0.53.0". The allowlist permits discovery; it does not
install plugins or resolve assets. See
Production profiles.
My memory source returns no records¶
Seed the exact asset name used by the pipeline (Extract(asset=...) /
Load(asset=...)):
Read load output using its asset:
Unknown profile name fails (PMCFG100)¶
Bare profile names that are not built-in templates fail closed:
python -m etlantic validate path.py:P --profile typo # PMCFG100
python -m etlantic validate path.py:P --profile typo --allow-adhoc-profile
SDK: resolve_profile("typo", allow_adhoc_profile=True). Prefer an explicit
Profile JSON path for CI.
Legacy profile bindings rejected (PMCFG111)¶
Profile JSON that only has "bindings" fails closed with PMCFG111. Prefer
"assets". Migrate with etlantic profile migrate PATH --write, or load once
with --accept-legacy-bindings /
Profile.from_dict(data, accept_legacy_bindings=True).
Plan fingerprint or schema errors¶
Persisted plans and run reports must include a wire "schema" field
(etlantic.plan/1 or etlantic.run_report/1). Missing or unknown schemas are
rejected. Fingerprints are verified on deserialize (default) and again before
compile/run—regenerate plans after upgrades that change participation rules.
See Migration 0.18 → 0.19.
Planning and execution use different profiles¶
Use one profile name for the whole workflow. The CLI defaults to
development when --profile is omitted (or default_profile from optional
etlantic.toml). Pass --profile explicitly when you want a different name.
Do not silently switch profile names within one workflow.
A Pandas, Polars, SQL, Spark, or Airflow example fails¶
Prefer PyPI docs paths first (no clone):
| Need | Install | Docs path |
|---|---|---|
Polars on an init project |
pip install 'etlantic[polars]==0.53.0' |
Polars tutorial |
Pandas on an init project |
pip install 'etlantic[pandas]==0.53.0' |
Pandas tutorial |
| SQL hello (SQLite) | pip install 'etlantic[sql]==0.53.0' |
SQL hello (PyPI) |
| Production trust / allowlist | core only | Capabilities CI starter |
Clone companions (optional, not in the wheel):
| Need | Install | Example |
|---|---|---|
| Polars portable kernel | pip install 'etlantic-polars==0.53.0' |
examples/portable_polars_kernel.py |
| Polars / Pandas native | pip install 'etlantic-polars==0.53.0' 'etlantic-pandas==0.53.0' |
examples/dataframe_parity.py |
| Polars ↔ Pandas Gate A | same as above | examples/interchange_polars_pandas.py |
| SQL fusion demo | pip install 'etlantic-sql==0.53.0' |
examples/sql_to_sql.py |
| PySpark | pip install 'etlantic-pyspark==0.53.0' (+ Java) |
examples/pyspark_local.py |
| Airflow compile | pip install 'etlantic-airflow==0.53.0' |
examples/airflow_compile.py |
| Medallantic | pip install 'medallantic==0.53.0' |
tests/medallantic/ |
Airflow compilation is available via etlantic-airflow. The shipped
etlantic-prefect local MVP is a direct-execution scheduler
(ExecutionScheduler), not a DAG compiler. Prefect deployment/serve and
Dagster compilers are not shipped.
Gate A / Polars ↔ Pandas interchange fails¶
Gate A (etlantic.interchange/1) shipped in 0.18.0 for Polars ↔
Pandas boundaries and remains available in 0.37.
| Symptom | Fix |
|---|---|
| Plugin not discovered | Install etlantic-polars==0.53.0 and etlantic-pandas==0.53.0; match core minor |
| Plan fails closed on descriptor / mechanism | Both plugins must advertise compatible interchange_mechanisms; see Plugin SDK |
| Expecting PySpark or SQL Gate A | Out of scope — stay on Polars↔Pandas or keep a single engine |
| Treating Arrow helpers as Gate A | Best-effort Arrow conversion is not the Gate A contract; use planned descriptors / evidence |
examples/interchange_polars_pandas.py missing |
Script is checkout-only; use Interchange docs or clone |
| SQL path unclear without clone | Use SQL hello (PyPI) first |
See Interchange Gate A FAQ and Polars ↔ Pandas Interchange.
PySpark fails before ETLantic executes a step¶
PySpark requires a compatible Java runtime as well as
etlantic-pyspark==0.53.0. Check both from the same environment:
Set JAVA_HOME to the supported JDK for your installed PySpark release. A
missing JVM, unsupported Java/PySpark pairing, or Python interpreter mismatch
must be fixed before ETLantic can create a local Spark session.
SQL reports a missing or invalid connection URL¶
Install etlantic-sql==0.53.0, select Profile(sql_engine="sql"), and provide
the URL expected by your binding or example. For the reference PostgreSQL
path:
Treat that value as a placeholder and never commit real credentials. SQLite is demo-only; the PostgreSQL plugin is the reference production path.
Airflow compiles but the generated DAG does not run¶
etlantic compile TARGET --target airflow validates a plan and emits a DAG
artifact. It does not provision Airflow, install your pipeline and plugin
dependencies into workers, configure connections, or seed runtime data.
Install matching packages in the Airflow runtime and configure its external
resources separately.
Commands in a design page do not exist¶
The shipped CLI includes:
init, doctor, validate, inspect, plan, profile, run, compile,
generate, diff, plugin, schema, reliability, viz, report
See the CLI reference. Pages marked Future design may show commands that are not shipped—check Capabilities first.
A virtual environment breaks after moving the repository¶
Virtual-environment entry points contain absolute paths. Delete and recreate the environment after moving or renaming a checkout:
Only run the removal command from the repository root after confirming
.venv is the project environment.
A repository checkout shadows the installed wheel¶
Python puts the current directory early on sys.path. Running from an
ETLantic source checkout can therefore import checkout code instead of the
0.53.0 wheel in your environment. Check the imported path:
For wheel-user testing, leave the repository directory and run from a clean
project. For contributor testing, use uv run ... from the checkout and do
not mix it with a separately installed wheel.
JSON / PipelineDefinition authoring¶
Fingerprint mismatch on load¶
etlantic.pipeline/1 documents include a fingerprint. If you hand-edit JSON
and change structure without refreshing the fingerprint, verify=True loads
fail closed. Prefer builders / write_pipeline_json, or recompute via
pipeline_fingerprint / with_fingerprint after intentional edits.
Unsupported schema¶
Only etlantic.pipeline/1 is accepted. A different schema string raises at
decode time—do not pass plan JSON (etlantic.plan/1) to definition loaders.
Validate/plan works; run fails missing callable¶
Definitions store implementation refs, not live functions. Register before run:
Class pipelines resolve @implementation decorators without this step. See
Programmatic authoring.
CLI TARGET vs class¶
python -m etlantic validate pipeline.json --profile development
python -m etlantic generate module:MyPipeline --kind definition -o pipeline.json
Cross-check diagnostic codes in Diagnostics.
M6 ops failure cookbook (observability / history / reports)¶
Milestone M6 shipped an observability and run-history pilot slice in 0.34—not
an enterprise control plane. Use this section when pilot ops tickets mention
durable_audit, history paths, report query, or optional OTel.
| Symptom | Likely cause | What to do |
|---|---|---|
| Durable audit / history write fails closed | Missing or unwritable history path; consumer misconfigured | Confirm history root exists and is writable; see Durable reports and Reports and history |
etlantic report query returns empty / errors |
No durable reports for the run id; wrong project root | Re-run with durable reports enabled; query from the same project dir; see Run reports |
| Observability provider not discovered | Package not installed; entry point not allowlisted in production | Install the provider package; set Profile.plugin_allowlist; see Observability today |
| OTel export missing | Optional extras not installed | Install etlantic[otel] / observability extras per Optional packages; OTel remains optional |
| Event consumer / run-history provider rejected | Trust / allowlist fail-closed | Production profiles require an explicit allowlist; see Plugin trust and protocol pages under Plugin SDK |
Deep links for authors shipping providers:
Engine-specific failures: also check the tutorial for your engine under Engines and ops, then return here.
Where to report a problem¶
Include the ETLantic version, Python version, command, complete traceback or diagnostic code, and a minimal pipeline definition in the issue report. Never include credentials or production data.