{"record":{"id":"5da12775aa363b59","repo":"harry0703/MoneyPrinterTurbo","slug":"segmented-control-options-cannot-be-empty-key","errorCode":null,"errorMessage":"segmented control options cannot be empty: {key}","messagePattern":"segmented control options cannot be empty: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"webui/Main.py","lineNumber":1735,"sourceCode":"        \"subtitle_background_color\",\n        \"rounded_subtitle_background\",\n    ):\n        _set_runtime_config(\"ui\", key, defaults[key])\n\n\n@st.dialog(tr(\"Final Prompt Preview\"), width=\"large\")\ndef render_script_prompt_preview(prompt):\n    \"\"\"展示将要发送给大模型的完整脚本生成提示词。\"\"\"\n    st.code(prompt, language=\"markdown\", wrap_lines=True)\n\n\ndef stable_segmented_control(\n    label, options, default_value, key, format_func=None, **kwargs\n):\n    \"\"\"使用稳定业务值创建单选分段控件，避免语言切换后状态被展示文案覆盖。\"\"\"\n    options = list(options)\n    if not options:\n        raise ValueError(f\"segmented control options cannot be empty: {key}\")\n\n    if default_value not in options:\n        default_value = options[0]\n\n    widget_key = localized_widget_key(key)\n    if st.session_state.get(widget_key) not in options:\n        st.session_state[widget_key] = default_value\n\n    return st.segmented_control(\n        label,\n        options=options,\n        selection_mode=\"single\",\n        required=True,\n        format_func=format_func or str,\n        key=widget_key,\n        **kwargs,\n    )\n","sourceCodeStart":1717,"sourceCodeEnd":1753,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/webui/Main.py#L1717-L1753","documentation":"stable_segmented_control() is the WebUI's wrapper around Streamlit segmented_control that pins selection state to stable business values (not display text), so language switches and reruns do not clobber the user's choice. Like its selectbox sibling, it raises ValueError when options is empty because a zero-option single-select control is unrenderable and has no valid state to store in session_state.","triggerScenarios":"Any call stable_segmented_control(label, options=[], ...) — typically an aspect-ratio / resolution / provider group whose options list is computed from config and collapses to zero entries (empty config file, all options filtered out for the current task type, or a missing data file).","commonSituations":"A newly added segmented control wired to a config key that does not exist yet; filtering options by provider capability that nothing satisfies in the current environment; refactoring that renames the config list leaving call sites with an empty default; localization files missing so derived option lists come back empty.","solutions":["Inspect the call site for the key named in the message and verify the data source feeding its options (config file / directory listing) actually returns entries","Provide a non-empty default options list at the call site instead of an expression that can evaluate to []","If zero options is a valid state, branch before the call: render a placeholder/info message instead of invoking stable_segmented_control"],"exampleFix":"# before\nstable_segmented_control(tr(\"Aspect Ratio\"), [r for r in RATINGS if r.enabled], default_value=\"16:9\", key=\"aspect_ratio\")\n\n# after\nratios = [r for r in RATINGS if r.enabled] or [\"16:9\"]\nstable_segmented_control(tr(\"Aspect Ratio\"), ratios, default_value=\"16:9\", key=\"aspect_ratio\")","handlingStrategy":"type-guard","validationCode":"options = list(options)\nif not options:\n    st.info(\"No options available for this control yet.\")\n    return  # skip rendering instead of raising","typeGuard":"def has_segment_options(options) -> bool:\n    \"\"\"Narrow before calling stable_segmented_control.\"\"\"\n    return bool(list(options or []))","tryCatchPattern":"try:\n    value = stable_segmented_control(label, options, default_value, key=key)\nexcept ValueError as exc:\n    if \"segmented control options cannot be empty\" in str(exc):\n        st.warning(f\"{label}: no options available\")\n        value = None\n    else:\n        raise","preventionTips":["Guard every call site with `if not options: render placeholder; return`","Give config-derived option lists a non-empty default so renames cannot blank them out","Add unit tests asserting non-empty options for each segmented control's data source"],"tags":["webui","streamlit","segmented-control","empty-options","ui-state"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}