{"record":{"id":"5a0ae5b83ee95cf4","repo":"HKUDS/Vibe-Trading","slug":"a-kind-cannot-be-both-external-and-internal-overl","errorCode":null,"errorMessage":"a kind cannot be both external and internal; overlapping: {', '.join(sorted(overlap))}","messagePattern":"a kind cannot be both external and internal; overlapping: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/performance.py","lineNumber":401,"sourceCode":"            internal, because assuming would understate the flow adjustment and\n            return a plausible wrong number.\n    \"\"\"\n    if flows is None:\n        return ()\n\n    external = (\n        DEFAULT_EXTERNAL_KINDS\n        if external_kinds is None\n        else frozenset(normalize_kind(kind) for kind in external_kinds)\n    )\n    internal = (\n        DEFAULT_INTERNAL_KINDS\n        if internal_kinds is None\n        else frozenset(normalize_kind(kind) for kind in internal_kinds)\n    )\n    overlap = external & internal\n    if overlap:\n        raise ValueError(\n            \"a kind cannot be both external and internal; overlapping: \"\n            f\"{', '.join(sorted(overlap))}\"\n        )\n\n    selected: list[tuple[date, float]] = []\n    for flow in flows:\n        if flow.is_valuation:\n            continue\n        if flow.kind in external:\n            selected.append((flow.date, -flow.amount))\n        elif flow.kind not in internal:\n            raise ValueError(\n                f\"cash-flow kind {flow.kind!r} on {flow.date} is classified \"\n                \"neither external nor internal, so it cannot be treated as \"\n                \"either. Pass external_kinds=[...] or internal_kinds=[...] to \"\n                \"say which side of the portfolio boundary it crosses. Known \"\n                f\"external: {', '.join(sorted(external))}. Known internal: \"\n                f\"{', '.join(sorted(internal))}.\"","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/performance.py#L383-L419","documentation":"external_flows classifies each cash-flow kind as either external (crosses the portfolio boundary, affects return) or internal (rebalancing inside the portfolio, ignored). This error fires when a kind appears in both the external and internal sets (or their defaults overlap with your custom sets), making the classification ambiguous.","triggerScenarios":"Calling external_flows, time_weighted_return, modified_dietz_return, or money_weighted_return and passing external_kinds={'dividend'} while 'dividend' is also in internal_kinds, or passing a custom set that overlaps with DEFAULT_INTERNAL_KINDS/DEFAULT_EXTERNAL_KINDS.","commonSituations":"Customizing external_kinds to include 'fee' or 'dividend' without removing it from internal_kinds; copying classification lists from another system where the same label means different things; defaults changing across library versions so a previously-fine custom list now overlaps.","solutions":["Remove the overlapping kind(s) listed in the error message from one of the two sets.","Prefer overriding only one of external_kinds/internal_kinds and let the defaults supply the other, after checking the shipped default sets.","Assert disjointness in your config before calling: external & internal == set()."],"exampleFix":"# before\nexternal_flows(flows,\n    external_kinds=['dividend', 'fee'],\n    internal_kinds=['fee', 'rebalance'],  # 'fee' in both -> ValueError\n)\n\n# after\nexternal_flows(flows,\n    external_kinds=['dividend', 'fee'],\n    internal_kinds=['rebalance'],\n)","handlingStrategy":"validation","validationCode":"ext, intl = set(external_kinds or DEFAULT_EXTERNAL_KINDS), set(internal_kinds or DEFAULT_INTERNAL_KINDS)\nassert not (ext & intl), f'overlap: {sorted(ext & intl)}'","typeGuard":null,"tryCatchPattern":"try:\n    flows_ext = external_flows(flows, external_kinds=ext, internal_kinds=intl)\nexcept ValueError as e:\n    if 'both external and internal' in str(e):\n        overlap = ext & intl\n        intl -= overlap  # resolve: external wins\n        flows_ext = external_flows(flows, external_kinds=ext, internal_kinds=intl)\n    else:\n        raise","preventionTips":["Define the classification once in config and unit-test disjointness.","Override only one of the two kind sets; derive the other from defaults minus the override.","Log the active external/internal sets at startup."],"tags":["quantlib","cash-flows","classification","config-overlap"],"backgroundTag":"config-value-conflict","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}