pola-rs/polars · error · ValueError

cannot {operation}: no storage_location found

Error message

cannot {operation}: no storage_location found

What it means

Raised by the Unity Catalog integration when the table metadata returned by `get_table_info` has a null `storage_location`. Polars needs the physical cloud path (e.g. s3://bucket/...) to actually read or write table data, so `CatalogClient.scan_table` and `write_table` refuse to continue via `_extract_location_and_data_format` (client.py:746). It surfaces as a ValueError with the message 'cannot scan table: no storage_location found'. Most commonly the object exists in the catalog but is not a physical table (a view, or a foreign/share object) or was registered without a location.

Source

Thrown at py-polars/src/polars/catalog/unity/client.py:751

        yield storage_update_options

        if not creds:
            table_id = self.table_id
            msg = (
                "did not receive credentials from temporary credentials API for "
                f"{table_id = }"
            )
            raise Exception(msg)  # noqa: TRY002

        yield creds, expiry


def _extract_location_and_data_format(
    table_info: TableInfo, operation: str
) -> tuple[str, DataSourceFormat]:
    if table_info.storage_location is None:
        msg = f"cannot {operation}: no storage_location found"
        raise ValueError(msg)

    if table_info.data_source_format is None:
        msg = f"cannot {operation}: no data_source_format found"
        raise ValueError(msg)

    return table_info.storage_location, table_info.data_source_format

View on GitHub (pinned to df599052da)

Solutions

  1. Check the object type: run `SHOW TABLES`/`DESCRIBE TABLE EXTENDED` or `client.get_table_info(...)` and inspect `table_info.table_type` and `table_info.storage_location` before scanning
  2. If it is a view, resolve its definition and scan the underlying base table instead
  3. Re-register/recreate the table with an explicit LOCATION (ALTER TABLE ... SET LOCATION or CREATE TABLE ... LOCATION) if the metadata is genuinely missing it
  4. If using Delta Sharing, fetch the shared table through a supported path rather than the catalog scan API

Example fix

# before
lf = catalog.scan_table("main", "sales", "daily_revenue_view")  # it's a view -> ValueError

# after
info = catalog.get_table_info("main", "sales", "daily_revenue_view")
if info.storage_location is None:
    raise SystemExit(f"{info.table_type} has no storage; resolve the base table")
lf = catalog.scan_table("main", "sales", "daily_revenue_base")
Defensive patterns

Strategy: validation

Validate before calling

info = catalog.get_table_info(catalog_name, namespace, table_name)
if info.storage_location is None:
    raise ValueError(
        f"{catalog_name}.{namespace}.{table_name} ({info.table_type}) has no storage_location"
    )

Type guard

from polars.catalog.unity.models import TableInfo

def is_scannable_table(info: TableInfo) -> bool:
    return info.storage_location is not None and info.table_type not in {"VIEW", "MATERIALIZED_VIEW"}

Try / catch

try:
    lf = catalog.scan_table(cat, ns, tbl)
except ValueError as e:
    if "no storage_location found" in str(e):
        info = catalog.get_table_info(cat, ns, tbl)
        raise RuntimeError(f"{tbl} is a {info.table_type}; scan its base table instead") from e
    raise

Prevention

When it happens

Trigger: Calling `catalog.scan_table(catalog_name, namespace, table_name)` or `catalog.write_table(df, ...)` where the Unity Catalog object is a VIEW (views have no storage location), a Delta Sharing proxy table, a table created with `CREATE VIEW`/external registration without LOCATION, or an API response where the storage_location field is missing/null. Also reproduced when `table_id`/name resolution points at the wrong object type.

Common situations: Pointing scan_table at a view name instead of its underlying table; using Databricks Unity Catalog objects shared via Delta Sharing that omit the location; tables created by a metastore migration that registered metadata without a storage path; SDK/API version mismatch where the field is not deserialized.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/516b35c79101b480. Report an issue: GitHub.