HKUDS/Vibe-Trading · error · TypeError

build_dcf_artifact: result must be a DCFResult, got {type(re

Error message

build_dcf_artifact: result must be a DCFResult, got {type(result).__name__}

What it means

build_dcf_artifact requires its result argument to be a DCFResult instance so the artifact's outputs are typed and diffable. Passing anything else (dict, DataFrame, a result from another model) is a TypeError.

Source

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

        result: The :class:`DCFResult` that call produced.
        generated_at: Timezone-aware timestamp of the run, supplied by the
            caller. See :func:`_require_generated_at`.
        capital_structure_basis: The ``capital_structure_basis`` the call used.
        discounting_convention: The ``discounting_convention`` the call used.
        terminal_value_method: The ``terminal_value_method`` the call used.
        gdp_growth_ceiling: The ``gdp_growth_ceiling`` the call used.

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

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

    canonical_inputs = {
        "config": {
            "capital_structure_basis": capital_structure_basis,
            "discounting_convention": discounting_convention,
            "terminal_value_method": terminal_value_method,
            "gdp_growth_ceiling": gdp_growth_ceiling,
        },
        "model_inputs": dict(inputs),
    }
    hash_leaves: dict[str, str] = {}
    readable_inputs: dict[str, Any] = {}
    _flatten(canonical_inputs, "$", hash_leaves, readable_inputs, None)
    input_hash = _hash_leaves(hash_leaves)

    readable_outputs: dict[str, Any] = {}

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass the DCFResult produced by the DCF engine (e.g. run_dcf(...) return value).
  2. If you changed the result shape, wrap it back into a DCFResult before building the artifact.
  3. For duck-typed substitutes, subclass or register against DCFResult (it must pass isinstance).

Example fix

# before
build_dcf_artifact(result={"ev": 1_000_000}, generated_at=ts)
# after
build_dcf_artifact(result=run_dcf(model, assumptions), generated_at=ts)
Defensive patterns

Strategy: type-guard

Validate before calling

from quantlib.valuation.models import DCFResult
if not isinstance(result, DCFResult):
    raise TypeError(f"expected DCFResult, got {type(result).__name__}")

Type guard

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

Prevention

When it happens

Trigger: build_dcf_artifact(result=some_dict, ...); passing a CompsResult or the raw outputs of run_dcf instead of the DCFResult dataclass; passing a namedtuple that mimics the fields.

Common situations: Refactoring the DCF engine to return dicts while artifact code still expects the dataclass; copy-pasting artifact build calls across models; duck-typed test doubles.

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/2ff4c01c3da04721. Report an issue: GitHub.