pola-rs/polars · error · NoDataError

no data, cannot infer schema

Error message

no data, cannot infer schema

What it means

`pl.from_dicts(data)` infers the schema from the dict contents; with an empty `data` and neither `schema` nor `schema_overrides` given, there is nothing to infer from and polars raises `NoDataError`. Supplying any schema information makes an empty input legal and yields a correctly-typed empty DataFrame.

Source

Thrown at py-polars/src/polars/convert/general.py:216

    >>> pl.from_dicts(
    ...     data,
    ...     schema=["a", "b", "c", "d"],
    ...     schema_overrides={"c": pl.Float64, "d": pl.String},
    ... )
    shape: (3, 4)
    ┌─────┬─────┬──────┬──────┐
    │ a   ┆ b   ┆ c    ┆ d    │
    │ --- ┆ --- ┆ ---  ┆ ---  │
    │ i64 ┆ i64 ┆ f64  ┆ str  │
    ╞═════╪═════╪══════╪══════╡
    │ 1   ┆ 4   ┆ null ┆ null │
    │ 2   ┆ 5   ┆ null ┆ null │
    │ 3   ┆ 6   ┆ null ┆ null │
    └─────┴─────┴──────┴──────┘
    """
    if not data and not (schema or schema_overrides):
        msg = "no data, cannot infer schema"
        raise NoDataError(msg)

    return pl.DataFrame(
        data,
        schema=schema,
        schema_overrides=schema_overrides,
        strict=strict,
        infer_schema_length=infer_schema_length,
    )


def from_records(
    data: Sequence[Any],
    schema: SchemaDefinition | None = None,
    *,
    schema_overrides: SchemaDict | None = None,
    strict: bool = True,
    orient: Orientation | None = None,
    infer_schema_length: int | None = N_INFER_DEFAULT,

View on GitHub (pinned to 5d8ebabf11)

Solutions

  1. Pass an explicit schema: `pl.from_dicts([], schema={'id': pl.Int64, 'name': pl.String})` — this also produces a typed empty frame.
  2. Short-circuit empty batches: `df = pl.DataFrame(schema=schema) if not data else pl.from_dicts(data, schema=schema)`.
  3. If the data should never be empty, investigate why it is before converting.

Example fix

# before
df = pl.from_dicts(api_results)  # api_results == [] -> NoDataError

# after
SCHEMA = {"id": pl.Int64, "score": pl.Float64}
df = pl.from_dicts(api_results, schema=SCHEMA)
Defensive patterns

Strategy: validation

Validate before calling

SCHEMA = {"id": pl.Int64, "score": pl.Float64}

def to_frame(rows: list[dict]) -> pl.DataFrame:
    if not rows:
        return pl.DataFrame(schema=SCHEMA)  # typed empty frame, no inference needed
    return pl.from_dicts(rows, schema=SCHEMA)

Try / catch

from polars.exceptions import NoDataError

try:
    df = pl.from_dicts(data)
except NoDataError:
    df = pl.DataFrame()  # or pl.DataFrame(schema=EXPECTED_SCHEMA)

Prevention

When it happens

Trigger: `pl.from_dicts([])`; `pl.from_dicts(rows)` where `rows` was filtered down to an empty list; the first batch of a looping/streaming job being empty.

Common situations: Dynamic pipelines where a source legitimately returns zero records; API responses that can be empty; unit tests with empty fixtures; date-range queries that match nothing.

Related errors


AI-assisted analysis of pola-rs/polars@5d8ebabf11 (2026-08-19). Data as JSON: /api/errors/e96dccc1e905b695. Report an issue: GitHub.