HKUDS/Vibe-Trading · error · TypeError

build_three_statement_artifact: result must be a ThreeStatem

Error message

build_three_statement_artifact: result must be a ThreeStatementProjection, got {type(result).__name__}

What it means

build_three_statement_artifact requires result to be a ThreeStatementProjection instance. Any other type — dict of DataFrames, a DCFResult, a legacy projection namedtuple — is a TypeError.

Source

Thrown at agent/src/quantlib/valuation/artifact.py:886

        result: The :class:`ThreeStatementProjection` that call produced.
        generated_at: Timezone-aware timestamp of the run, supplied by the
            caller.
        circularity_tolerance: The ``circularity_tolerance`` the call used.
        max_circularity_iterations: The ``max_circularity_iterations`` the
            call used.
        balance_tolerance: The ``balance_tolerance`` the call used.

    Returns:
        A ``model_name="three_statement"`` :class:`ModelArtifact`.

    Raises:
        TypeError: If ``generated_at`` is not a ``datetime``, or ``result``
            is not a :class:`ThreeStatementProjection`.
        ValueError: If ``generated_at`` is timezone-naive.
    """
    generated_at = _require_generated_at(generated_at, "build_three_statement_artifact")
    if not isinstance(result, ThreeStatementProjection):
        raise TypeError(
            "build_three_statement_artifact: result must be a "
            f"ThreeStatementProjection, got {type(result).__name__}"
        )

    canonical_inputs = {
        "config": {
            "circularity_tolerance": circularity_tolerance,
            "max_circularity_iterations": max_circularity_iterations,
            "balance_tolerance": balance_tolerance,
        },
        "opening": dict(opening),
        "drivers": {key: list(value) for key, value in drivers.items()},
    }
    hash_leaves: dict[str, str] = {}
    readable_inputs: dict[str, Any] = {}
    _flatten(canonical_inputs, "$", hash_leaves, readable_inputs, None)
    input_hash = _hash_leaves(hash_leaves)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass the ThreeStatementProjection returned by the projection engine.
  2. If you hold partial data, construct a ThreeStatementProjection explicitly.
  3. Update mocks/fakes to subclass ThreeStatementProjection.

Example fix

# before
build_three_statement_artifact(result=(income_df, balance_df, cash_df), generated_at=ts)
# after
build_three_statement_artifact(result=run_three_statement(model, assumptions), generated_at=ts)
Defensive patterns

Strategy: type-guard

Validate before calling

from quantlib.valuation.models import ThreeStatementProjection
assert isinstance(result, ThreeStatementProjection)

Type guard

from quantlib.valuation.models import ThreeStatementProjection
def is_three_statement_projection(value) -> bool:
    return isinstance(value, ThreeStatementProjection)

Prevention

When it happens

Trigger: build_three_statement_artifact(result={"income": df, ...}, ...); passing a DCFResult or an older projection class; passing the engine's raw tuple return.

Common situations: Upgrading the projection engine whose return type changed; copy-pasting from the DCF artifact builder; mock objects in tests that aren't subclasses.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/19b4bb13d3693f2f. Report an issue: GitHub.