{"record":{"id":"f10d0da3feb6db31","repo":"nautechsystems/nautilus_trader","slug":"chart-name-cannot-be-empty","errorCode":null,"errorMessage":"Chart name cannot be empty","messagePattern":"Chart name cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/nautilus_trader/analysis/tearsheet.py","lineNumber":282,"sourceCode":"        If name is empty or func is not callable.\n\n    Examples\n    --------\n    >>> # As a decorator\n    >>> @register_chart(\"my_custom_chart\")\n    ... def create_custom_chart(returns: pd.Series, **kwargs) -> go.Figure:\n    ...     fig = go.Figure()\n    ...     # ... custom visualization logic\n    ...     return fig\n    >>>\n    >>> # Or called directly\n    >>> register_chart(\"another_chart\", create_custom_chart)\n\n    \"\"\"\n    _require_not_none(name, \"name\")\n\n    if not name.strip():\n        raise ValueError(\"Chart name cannot be empty\")\n\n    if func is None:\n\n        def decorator(f: Callable) -> Callable:\n            if not callable(f):\n                raise ValueError(f\"Chart function must be callable, was {type(f)}\")\n            _CHART_REGISTRY[name] = f\n            return f\n\n        return decorator\n\n    if not callable(func):\n        raise ValueError(f\"Chart function must be callable, was {type(func)}\")\n\n    _CHART_REGISTRY[name] = func\n    return None\n\n","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/python/nautilus_trader/analysis/tearsheet.py#L264-L300","documentation":"A password and/or app key was supplied but no username, so BetfairCredential::resolve rejects the incomplete triple before any login attempt. As with other partial states, providing any field in config disables the environment fallback, which commonly triggers this when the username lives only in the environment but the password is set in config.","triggerScenarios":"Config sets password and/or app_key with no username; or the environment has BETFAIR_PASSWORD/BETFAIR_APP_KEY but BETFAIR_USERNAME is unset or typo'd; username key dropped during config migration.","commonSituations":"Credentials sourced half from a vault and half from env; YAML key renamed from user to username; variable dropped when moving between deployment environments.","solutions":["Set the username (config field or BETFAIR_USERNAME)","Keep all three credentials in one place - all config or all environment","Run a preflight completeness check that lists exactly which of the three are missing"],"exampleFix":"// before\n.password(\"secret\".into())\n.app_key(\"xxxxxxx\".into()) // username assumed from env (never read)\n\n// after\n.username(\"better\".into())\n.password(\"secret\".into())\n.app_key(\"xxxxxxx\".into())","handlingStrategy":"validation","validationCode":"anyhow::ensure!(\n    username.is_some() || (password.is_none() && app_key.is_none()),\n    \"password/app_key provided but username is missing\"\n);","typeGuard":"fn no_credentials_without_username(username: Option<&str>, password: Option<&str>, app_key: Option<&str>) -> bool {\n    username.is_some() || (password.is_none() && app_key.is_none())\n}","tryCatchPattern":null,"preventionTips":["Provide username first when configuring credentials incrementally","Keep the triple in a single secret store entry","Add a config schema check that the three fields are all-or-none"],"tags":["betfair","credentials","config","validation","rust"],"backgroundTag":"incomplete-credentials","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}