{"record":{"id":"7680647240229792","repo":"HKUDS/Vibe-Trading","slug":"portfolio-weights-cannot-be-empty","errorCode":null,"errorMessage":"portfolio_weights cannot be empty","messagePattern":"portfolio_weights cannot be empty","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/factormodel.py","lineNumber":634,"sourceCode":"    Args:\n        portfolio_weights: Asset weights in the portfolio.\n        exposures: Asset factor exposures (rows = assets, columns = factors).\n        factor_cov: Covariance matrix of factor returns (K x K).\n        specific_variances: Asset-specific (idiosyncratic) return variances.\n            Defaults to zero if omitted.\n\n    Returns:\n        :class:`FactorRiskDecomposition` containing total/factor/specific\n        variances, volatilities, marginal contributions to risk (MCR), and\n        percentage contributions to risk (PCR) per factor and per asset.\n\n    Raises:\n        ValueError: If weights or matrices are empty, contain non-finite values,\n            or share no common assets or factors.\n    \"\"\"\n    w_series = pd.Series(portfolio_weights, dtype=float)\n    if w_series.empty:\n        raise ValueError(\"portfolio_weights cannot be empty\")\n    if not np.isfinite(w_series.values).all():\n        raise ValueError(\"portfolio_weights contains non-finite values\")\n\n    if not isinstance(exposures, pd.DataFrame) or exposures.empty:\n        raise ValueError(\"exposures must be a non-empty DataFrame\")\n    if not np.isfinite(exposures.values).all():\n        raise ValueError(\"exposures contains non-finite values\")\n\n    if not isinstance(factor_cov, pd.DataFrame) or factor_cov.empty:\n        raise ValueError(\"factor_cov must be a non-empty DataFrame\")\n    if not np.isfinite(factor_cov.values).all():\n        raise ValueError(\"factor_cov contains non-finite values\")\n\n    # Align assets\n    assets = w_series.index.intersection(exposures.index)\n    if assets.empty:\n        raise ValueError(\n            f\"No matching assets between weights ({sorted(w_series.index)}) and exposures ({sorted(exposures.index)})\"","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/factormodel.py#L616-L652","documentation":"factor_risk_decomposition refuses an empty portfolio_weights input because risk of nothing is undefined (and downstream linear algebra would fail anyway).","triggerScenarios":"Passing portfolio_weights={}, an empty list, or an empty pd.Series.","commonSituations":"Empty book passed to a nightly risk job; positions filtered out by a universe screen before the call.","solutions":["Check len(portfolio_weights) before calling","Log the portfolio ID/weights source when it comes up empty","Return a zero-risk result upstream instead of calling the API"],"exampleFix":"# before\nrisk = factor_risk_decomposition(w, X, F)\n# after\nrisk = factor_risk_decomposition(w, X, F) if len(w) else None","handlingStrategy":"validation","validationCode":"assert len(portfolio_weights) > 0","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guard nightly jobs with an empty-book check","Return structured zero-risk result instead of calling the API"],"tags":["quantlib","factormodel","empty-input","validation"],"backgroundTag":"empty-input-validation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}