{"record":{"id":"5a0e82b73867e305","repo":"ZhuLinsen/daily_stock_analysis","slug":"unsafe-config","errorCode":"unsafe_config","errorMessage":"unsafe_config at configuration for backend {backend}","messagePattern":"unsafe_config at configuration for backend (.+?)","errorType":"error_code","errorClass":"GenerationError","httpStatus":null,"severity":"error","filePath":"src/llm/local_cli_backend.py","lineNumber":2040,"sourceCode":"        for event in events:\n            event_type_lower = str(event.get(\"type\") or \"\").strip().lower()\n            if (\n                _opencode_blocked_event_reason(event, event_type_lower)\n                or bool(event.get(\"error\"))\n                or event.get(\"is_error\") is True\n            ):\n                return True\n    except LocalCliExtractionError:\n        return False\n    return False\n\n\ndef resolve_local_cli_preset(preset_id: str) -> LocalCliPreset:\n    \"\"\"Return a safe preset or raise a structured unsafe_config error.\"\"\"\n\n    preset = SAFE_LOCAL_CLI_PRESETS.get((preset_id or \"\").strip().lower())\n    if preset is None:\n        raise GenerationError(\n            error_code=GenerationErrorCode.UNSAFE_CONFIG,\n            stage=\"configuration\",\n            retryable=False,\n            fallbackable=False,\n            backend=preset_id or \"local_cli\",\n            provider=preset_id or \"local_cli\",\n            details={\n                \"reason\": \"unknown_local_cli_preset\",\n                \"preset_id\": preset_id,\n                \"allowed_presets\": sorted(SAFE_LOCAL_CLI_PRESETS),\n            },\n        )\n    return preset\n\n\nclass LocalCliGenerationBackend(GenerationBackend):\n    \"\"\"Restricted subprocess-backed generation backend.\"\"\"\n","sourceCodeStart":2022,"sourceCodeEnd":2058,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/llm/local_cli_backend.py#L2022-L2058","documentation":"A structured GenerationError with code unsafe_config raised at the configuration stage when resolve_local_cli_preset cannot find the requested preset_id in SAFE_LOCAL_CLI_PRESETS. Presets are an explicit allowlist of vetted local CLI configurations; unknown IDs are rejected as unsafe rather than silently defaulted. It is non-retryable and non-fallbackable by design.","triggerScenarios":"Calling resolve_local_cli_preset('claude-code') (or any ID not in the allowlist), passing an empty or misspelled preset string, or passing a casing/whitespace variant not covered by the .strip().lower() normalization. The details payload includes reason=unknown_local_cli_preset and the sorted list of allowed presets.","commonSituations":"A config file or env var names a preset removed in a refactor; user typos in LOCAL_CLI_PRESET; version mismatch where the deployed code has a smaller allowlist than the config expects; copy-pasting a preset ID from newer docs into an older install.","solutions":["Read the allowed_presets list from the error details (or inspect SAFE_LOCAL_CLI_PRESETS) and set the preset ID to one of those exact values","Fix typos, casing, and stray whitespace in the configured preset ID (normalization only handles case and surrounding whitespace)","If the preset was renamed, update the config to the new identifier from the current codebase","Upgrade or pin the deployment so its allowlist matches the preset the config references"],"exampleFix":"# before\nLOCAL_CLI_PRESET=claudecode\n\n# after\nLOCAL_CLI_PRESET=claude-code  # must match an entry in SAFE_LOCAL_CLI_PRESETS","handlingStrategy":"validation","validationCode":"from src.llm.local_cli_backend import SAFE_LOCAL_CLI_PRESETS\n\ndef is_known_preset(preset_id: str) -> bool:\n    return (preset_id or \"\").strip().lower() in SAFE_LOCAL_CLI_PRESETS","typeGuard":"from typing import Any\nfrom src.llm.local_cli_backend import SAFE_LOCAL_CLI_PRESETS\n\ndef is_safe_preset_id(value: Any) -> bool:\n    return isinstance(value, str) and value.strip().lower() in SAFE_LOCAL_CLI_PRESETS","tryCatchPattern":"try:\n    preset = resolve_local_cli_preset(preset_id)\nexcept GenerationError as exc:\n    if exc.error_code == GenerationErrorCode.UNSAFE_CONFIG:\n        log.error(\"Unknown preset %r; allowed: %s\", preset_id, exc.details[\"allowed_presets\"])\n    raise","preventionTips":["Expose allowed preset IDs in UI dropdowns / config docs so users cannot type free text","Validate preset IDs at config load, not at generation time","Treat preset renames as breaking config changes and migrate stored settings on upgrade"],"tags":["config","llm","cli","validation","allowlist"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}