Skip to content

Errors

How to read factrix errors and which exception class to catch.

TL;DR

import factrix as fx
from factrix.metrics import ic

try:
    results = fx.evaluate(
        data, 
        metrics={"ic": ic(inference=fx.inference.NEWEY_WEST)}, 
        factor_cols=["factor"]
    )
except fx.UserInputError as exc:
    # User typed the wrong thing — typo, unknown name, wrong column.
    # The message carries a fuzzy suggestion + a docs link.
    print(exc)
except fx.IncompatibleAxisError as exc:
    # Axis miswire.
    ...
except fx.InsufficientSampleError as exc:
    # Sample threshold is below the required hard floor.
    # exc.actual_periods and exc.required_periods carry details.
    ...
except fx.FactrixError as exc:
    # Catch-all for anything else factrix raises.
    ...

All factrix-raised exceptions inherit from FactrixError, so a single except fx.FactrixError blocks every library-raised failure.

Exception hierarchy

FactrixError                       # base
├── IncompatibleAxisError          # (scope, density, metric) is not a legal cell
├── IncompatibleInferenceError     # inference= outside the metric's applicable-inference allowlist
├── InsufficientSampleError        # T below SampleThreshold on a TIMESERIES/PANEL procedure
├── UserInputError                 # named-set typo / type mismatch / dataset schema error
└── CycleError                     # MetricSpec.requires declares a dependency cycle
Exception When you see it What it carries
IncompatibleAxisError (scope, density, metric) is not a legal cell
IncompatibleInferenceError inference= outside the metric's applicable_inference allowlist .func_name, .value, .applicable
InsufficientSampleError T below the procedure floor .actual_periods, .required_periods
UserInputError Unknown metric, column not in data, wrong type structured .field, .value, .candidates, .suggestions, .expected, .docs_url
CycleError A custom metric's MetricSpec.requires forms a dependency cycle

Error → fix mapping

Concrete messages, what triggers them, and where to look for the fix.

Data-schema failures

Message hint Trigger Fix
factor_cols 'X' not in data columns Typo or wrong column name Check data.columns; pass the actual name to factor_cols=. See Data schema.
forward_return column missing Forgot the preprocess step compute_forward_return(raw, forward_periods=h) before evaluate. See Preparing data.

Structural and sample failures

Exception / message Trigger Fix
IncompatibleAxisError: (scope, density, metric) is not a legal cell Combination that the dispatch table never registers Use compatible axes. Check list_metrics or inspect_data to find applicable metrics.
InsufficientSampleError: T below required Sample size below the procedure's hard floor Read .actual_periods and .required_periods. The fix is either more data, or switching to a less restrictive metric.

User-input failures (UserInputError)

Every UserInputError carries structured attributes (see Reading a UserInputError). Common triggers and fix paths:

Message hint Trigger Fix
unknown metrics='...' Typo or metric not applicable to the data inspect_data(data).usable enumerates the metrics applicable to the data shape. See list_metrics for the full catalog.
invalid expand_over=[...] One or more expand_over keys missing on some results' params The message lists every (factor, missing_key) pair in one pass. All results in the family must carry the key in .params; populate it consistently, or drop the key from expand_over. A key found on .metadata instead is called out separately — bookkeeping never partitions a family.
Expected: list[EvaluationResult], got ... Passing the wrong artifact type to a screening function Screening (bhy, partial_conjunction, bhy_hierarchical) consumes list[EvaluationResult].

Reading a UserInputError

Every user-facing raise that takes a named input renders the same three-part message:

bhy(): unknown expand_over='univere_id'
  Did you mean: "universe_id"?
  Available: ['regime_id', 'sector', 'universe_id']
  Docs: https://awwesomeman.github.io/factrix/api/bhy#expand_over
Line What to look at
<func_name>(): unknown <field>=<value> Which kwarg / column triggered the raise, and what value was received.
Did you mean: "..." Top-3 fuzzy candidates (omitted when nothing matches above the cutoff).
Available: [...] The full legal set.
Docs: https://... The function's deployed-docs anchor.

For type / shape mismatches, the second line reads Expected: <shape> instead of Did you mean: ....

Programmatic recovery

The structured attributes are the contract — read them, do not parse the rendered message:

import factrix as fx

bad: dict[str, object] = {}
for factor_col in candidates:
    try:
        results = fx.evaluate(data, metrics=metrics, factor_cols=[factor_col])
    except fx.UserInputError as exc:
        bad[exc.field] = exc.value
        # exc.suggestions carries top-3 fuzzy matches when applicable
Attribute Meaning
func_name The calling function (e.g. "bhy", "evaluate").
field The kwarg / column name that failed validation.
value The value the caller passed in.
candidates Sorted tuple of legal names (named-set branch); () otherwise.
suggestions difflib top-3 matches against candidates; () when none.
expected Human-readable shape (mismatch branch); None otherwise.
docs_url Resolved deployed-docs URL for the function.

Class reference

Autodoc anchors for cross-references of the form [FactrixError][factrix.FactrixError] from any docs page.

Base

factrix.FactrixError

Bases: Exception

Base for all factrix-raised errors.

User-input failures

factrix.UserInputError

UserInputError(*, func_name: str, field: str, value: object, candidates: Iterable[object] | None = None, expected: str | None = None, docs_path: str)

Bases: FactrixError, ValueError

User-supplied input does not match expected names or types.

Raised for typos in named-set kwargs (metric / estimator / params key / column name) or input-type mismatches. Multi-inherits from :class:ValueError so ecosystem code (pytest.raises(ValueError), generic except ValueError) keeps working.

Structured attributes carry the diagnostic so callers (sub-issue raises, LLM agents) do not parse the rendered message:

  • func_name: the calling function name (no parens)
  • field: the kwarg / column name that failed validation
  • value: the value the caller passed in
  • candidates: tuple of legal names (named-set branch); empty otherwise
  • suggestions: difflib top-3 fuzzy matches against candidates
  • expected: human-readable shape (type-mismatch branch); None otherwise
  • docs_url: deployed-docs URL for the function

Structural and sample failures

factrix.IncompatibleAxisError

Bases: FactrixError

(scope, density, metric) tuple is not a legal analysis cell.

Covers e.g. density=SPARSE paired with metric=IC, or (INDIVIDUAL, DENSE) with metric=None.

factrix.IncompatibleInferenceError

IncompatibleInferenceError(*, func_name: str, value: object, applicable: Iterable[str])

Bases: FactrixError

inference= is not in the metric's applicable-inference allowlist.

Each metric that exposes inference= declares an applicable_inference frozenset of the methods it actually dispatches. Passing anything outside it — a valid Inference the metric does not vet (e.g. HansenHodrick to ic) or a non- Inference object — raises here instead of silently running an unintended test or falling back to the default.

Structured attributes carry the diagnostic so callers do not parse the rendered message:

  • func_name: the calling metric name (no parens)
  • value: the value the caller passed as inference
  • applicable: tuple of allowed inference names for that metric

factrix.InsufficientSampleError

InsufficientSampleError(message: str, *, actual_periods: int, required_periods: int)

Bases: FactrixError

T < MIN_PERIODS_HARD for a TIMESERIES procedure.

Below the floor, Newey-West (NW) heteroskedasticity-and-autocorrelation-consistent (HAC) SE is too biased for primary_p to be trustworthy. Raised at evaluate-time. actual_periods and required_periods carry the numbers so callers can recover or aggregate programmatically (review fix UX-3).

Custom-metric wiring failures

factrix.CycleError

Bases: FactrixError

Raised when MetricSpec.requires declares a dependency cycle.

A :class:FactrixError, so except factrix.FactrixError catches it alongside every other library-raised failure.