pola-rs/polars · error · TypeError
cannot use NoopCatalog with
Error message
cannot use NoopCatalog with {fn_name}() What it means
The Iceberg catalog resolved from the API parameter or environment defaulted to polars' NoopCatalog, which is a placeholder that performs no real catalog operations. polars raises TypeError because scan/sink functions like scan_iceberg or sink_iceberg cannot do anything useful without a functional catalog. This is a fail-fast guard raised from _from_api_parameter_or_environment_default.
Solutions
- Pass an explicit catalog argument to the API call (catalog='catalog_name' or a full URI).
- Set the catalog configuration in the environment (e.g. PYICEBERG_CATALOG__<name>__URI=...) or pyiceberg config so the default catalog resolves to a real implementation.
- Verify the catalog name matches one defined in your ~/.pyiceberg.yaml / .pyiceberg.yaml.
Example fix
// before
pl.scan_iceberg("db.table") # no catalog configured -> NoopCatalog
// after
pl.scan_iceberg("db.table", catalog="my_catalog") # or set PYICEBERG_CATALOG env config Defensive patterns
Strategy: validation
Validate before calling
catalog = catalog or os.environ.get("PYICEBERG_CATALOG")
if not catalog or catalog_is_noop(catalog):
raise ValueError("Configure a real Iceberg catalog before scanning") Type guard
def is_usable_catalog(cfg: IcebergCatalogConfig) -> bool:
return cfg.class_ is not NoopCatalog Try / catch
try:
df = pl.scan_iceberg(uri, catalog=cat).collect()
except TypeError as e:
if "NoopCatalog" in str(e):
df = pl.scan_iceberg(uri, catalog="default").collect()
else:
raise Prevention
- Always pass an explicit catalog argument to Iceberg APIs in production code.
- Set PYICEBERG_CATALOG env vars in deployment config, not just locally.
- Add a startup check that the catalog resolves to a real implementation, not NoopCatalog.
When it happens
Trigger: Calling an Iceberg API (e.g. scan_iceberg) without passing a catalog parameter while no valid catalog is configured in the environment, so IcebergCatalogConfig.from_catalog(default_catalog) resolves to class_ == NoopCatalog.
Common situations: Developers forget to set the catalog URI (e.g. PYICEBERG_CATALOG env var or polars.Config), or run in an environment where pyiceberg falls back to its default 'sql'/noop-style catalog; also happens when the catalog name passed does not match any configured catalog.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- failed to load catalog for
- cannot sink to static Iceberg table
- iceberg snapshot ID not found
- iceberg snapshot ID not found
- iceberg: unknown value for reader_override
AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18).
Data as JSON: /api/errors/33669d74c5ba5b8c.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/io/iceberg/_dataset.py:198
)
if fn_name == "scan_iceberg"
else ""
)
msg = (
f"failed to load catalog for {fn_name}() ({error = }). "
"Configure the default PyIceberg catalog, or pass "
"a catalog via the 'catalog' parameter, or pass a PyIceberg "
"table object instead of the name."
f"{static_metadata_hint}"
)
raise ComputeError(msg) from error
catalog_config = IcebergCatalogConfig.from_catalog(default_catalog)
if catalog_config.class_ == NoopCatalog:
msg = f"cannot use NoopCatalog with {fn_name}()"
raise TypeError(msg)
return catalog_config
@dataclass(kw_only=True)
class IcebergScanResolver:
"""
Iceberg scan resolver.
Defers scan resolution to run during IR resolution.
"""
table: IcebergTableWrap
snapshot_id: int | None
from_snapshot_id_exclusive: int | None
to_snapshot_id_inclusive: int | None
reader_override: Literal["native", "pyiceberg"] | None
use_metadata_statistics: boolView on GitHub (pinned to fe841f959e)