{"record":{"id":"2cd50d65eba50249","repo":"oraios/serena","slug":"symbol-info-budget-must-be-a-number-or-null-got","errorCode":null,"errorMessage":"symbol_info_budget must be a number or null, got: {symbol_info_budget_raw}","messagePattern":"symbol_info_budget must be a number or null, got: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/serena/config/serena_config.py","lineNumber":613,"sourceCode":"                ) from e\n\n        # Validate activation_command_timeout\n        activation_command_timeout_raw = data.get(\"activation_command_timeout\", 180.0)\n        try:\n            activation_command_timeout = float(activation_command_timeout_raw)\n        except (TypeError, ValueError) as e:\n            raise ValueError(f\"activation_command_timeout must be a number, got: {activation_command_timeout_raw}\") from e\n        if activation_command_timeout <= 0:\n            raise ValueError(f\"activation_command_timeout must be positive, got: {activation_command_timeout}\")\n\n        # Validate symbol_info_budget\n        symbol_info_budget_raw = data[\"symbol_info_budget\"]\n        symbol_info_budget = symbol_info_budget_raw\n        if symbol_info_budget is not None:\n            try:\n                symbol_info_budget = float(symbol_info_budget_raw)\n            except (TypeError, ValueError) as e:\n                raise ValueError(f\"symbol_info_budget must be a number or null, got: {symbol_info_budget_raw}\") from e\n            if symbol_info_budget < 0:\n                raise ValueError(f\"symbol_info_budget cannot be negative, got: {symbol_info_budget}\")\n\n        language_backend_value = data.get(\"language_backend\")\n        language_backend = LanguageBackend.from_str(language_backend_value) if language_backend_value else None\n\n        line_ending_value = data.get(\"line_ending\")\n        line_ending = LineEnding.from_str(line_ending_value) if line_ending_value else None\n\n        # gracefully handle user errors: incorrect use of None/empty where a list is required\n        ignored_paths = data[\"ignored_paths\"] or []\n        fixed_tools = data[\"fixed_tools\"] or []\n        excluded_tools = data[\"excluded_tools\"] or []\n        included_optional_tools = data[\"included_optional_tools\"] or []\n        additional_workspace_folders = data.get(\"ls_additional_workspace_folders\") or []\n\n        if \"base_modes\" in data and data[\"base_modes\"] is not None:\n            log.warning(\"The base_modes setting in project.yml is deprecated and will be ignored.\")","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/config/serena_config.py#L595-L631","documentation":"_from_dict validates symbol_info_budget: it may be null (disabled) or a non-negative number, anything else raises ValueError. The budget controls how many symbols Serena reports per tool call, so the config parser coerces it to float and rejects negative values with a separate message.","triggerScenarios":"ProjectConfig.autogenerate(..., symbol_info_budget='unlimited') or a project.yml with symbol_info_budget: 'high' / true / a list; any non-numeric, non-null YAML scalar. Missing key raises KeyError instead since data['symbol_info_budget'] is accessed directly.","commonSituations":"Hand-editing project.yml with a descriptive word like 'default' or 'unlimited' instead of a number; passing a string from a CLI flag without conversion; YAML auto-typing surprises (e.g. `no` parsed as boolean False is fine as falsy? no — False is not None so float(False)=0.0, but 'none' string fails).","solutions":["Set symbol_info_budget to a non-negative number (e.g. symbol_info_budget: 50) or explicit null to disable the limit","Convert string inputs before passing: float(value) if value not in (None, 'null') else None","Ensure the key exists in project.yml (absent key raises KeyError, not this error)","Check for negative values too — a following check rejects symbol_info_budget < 0"],"exampleFix":"// before (project.yml)\nsymbol_info_budget: \"unlimited\"\n// after (project.yml)\nsymbol_info_budget: 100","handlingStrategy":"type-guard","validationCode":"raw = data.get(\"symbol_info_budget\")\nif raw is not None and not isinstance(raw, (int, float)):\n    raise TypeError(f\"symbol_info_budget must be a number or null, got {raw!r}\")\nif raw is not None and float(raw) < 0:\n    raise ValueError(f\"symbol_info_budget cannot be negative, got {raw}\")","typeGuard":"def is_number_or_none(v) -> bool:\n    return v is None or (isinstance(v, (int, float)) and not isinstance(v, bool))","tryCatchPattern":"try:\n    config = ProjectConfig.load(project_root)\nexcept ValueError as e:\n    if 'symbol_info_budget' in str(e):\n        logger.error(\"symbol_info_budget must be a number or null in project.yml: %s\", e)\n    raise","preventionTips":["Write a plain number (e.g. 100) or explicit `null` in project.yml — never words like 'unlimited'","Always include the key (missing key raises KeyError since it's read via data[...])","Convert CLI/env string inputs to float or None before passing to autogenerate","Remember negative numbers fail a separate check — clamp with max(0, value)"],"tags":["python","configuration","validation","type-error"],"backgroundTag":"schema-validation-failed","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}