pola-rs/polars · error · FileNotFoundError

no dynamic library found at path: {path}

Error message

no dynamic library found at path: {path}

What it means

register_plugin_function resolves plugin_path: a file path is used directly; a directory is scanned for a dynamic library (suffix .so, .dll, or .pyd). If none is found, FileNotFoundError is raised. Paths are resolved relative to the active virtualenv (sys.prefix) unless use_abs_path=True.

Source

Thrown at py-polars/src/polars/plugins.py:137

    # https://docs.rs/serde-pickle/latest/serde_pickle/
    return pickle.dumps(kwargs, protocol=5)


@lru_cache(maxsize=16)
def _resolve_plugin_path(path: Path | str, *, use_abs_path: bool = False) -> Path:
    """Get the file path of the dynamic library file."""
    if not isinstance(path, Path):
        path = Path(path)

    if path.is_file():
        return _resolve_file_path(path, use_abs_path=use_abs_path)

    for p in path.iterdir():
        if _is_dynamic_lib(p):
            return _resolve_file_path(p, use_abs_path=use_abs_path)

    msg = f"no dynamic library found at path: {path}"
    raise FileNotFoundError(msg)


def _is_dynamic_lib(path: Path) -> bool:
    return path.is_file() and path.suffix in (".so", ".dll", ".pyd")


def _resolve_file_path(path: Path, *, use_abs_path: bool = False) -> Path:
    venv_path = Path(sys.prefix)

    if use_abs_path:
        return path.resolve()
    else:
        try:
            file_path = path.relative_to(venv_path)
        except ValueError:  # Fallback
            file_path = path.resolve()

    return file_path

View on GitHub (pinned to df599052da)

Solutions

  1. Verify a .so/.dll/.pyd actually exists under the path (ls the directory) and point plugin_path at it or its containing dir
  2. Reinstall the plugin package for your platform/Python (pip install --force-reinstall <plugin>)
  3. Set use_abs_path=True when the path must not be interpreted relative to sys.prefix, or pass the absolute library file path
  4. If building from source, build first (maturin develop / cargo build --release) so the artifact exists

Example fix

# before
register_plugin_function(
    namespace='mathx', function='logistic', plugin_path='polars-plugin/src',  # no .so there
)

# after
register_plugin_function(
    namespace='mathx', function='logistic',
    plugin_path=Path('polars-plugin/target/release').resolve(),  # dir containing libmathx.so
    use_abs_path=True,
)
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path
p = Path(plugin_path)
has_lib = p.is_file() or any(
    q.suffix in ('.so', '.dll', '.pyd') for q in (p.iterdir() if p.is_dir() else [])
)
if not has_lib:
    raise FileNotFoundError(f'no dynamic library under {p}; build/install the plugin first')

Try / catch

from polars.plugins import register_plugin_function
try:
    fn = register_plugin_function(namespace='mathx', function='logistic', plugin_path=lib_dir)
except FileNotFoundError as exc:
    raise RuntimeError(
        f'polars plugin not built/installed at {lib_dir!r}; run maturin develop'
    ) from exc

Prevention

When it happens

Trigger: Passing plugin_path pointing at a directory with no compiled library (e.g. the Python package dir instead of the dir containing the .so); a plugin wheel built for another platform/Python; a source checkout where maturin/cargo build output is elsewhere; venv mismatch making a relative path resolve to the wrong prefix.

Common situations: First use of a new polars plugin (e.g. polars_ols, polars_ts); CI or deployment environments where the plugin wheel was not installed for the platform; switching conda/system Python breaks venv-relative resolution.

Related errors


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