{"record":{"id":"5d4e55780852e68a","repo":"freqtrade/freqtrade","slug":"protections-must-specify-either-unlock-at-stop","errorCode":null,"errorMessage":"Protections must specify either `unlock_at`, `stop_duration` or `stop_duration_candles`.\\nPlease fix the protection {prot.get('method')}.","messagePattern":"Protections must specify either `unlock_at`, `stop_duration` or `stop_duration_candles`\\.\\\\nPlease fix the protection (.+?)\\.","errorType":"validation","errorClass":"ConfigurationError","httpStatus":null,"severity":"error","filePath":"freqtrade/plugins/protectionmanager.py","lineNumber":121,"sourceCode":"                        f\"Invalid date format for unlock_at: {config_unlock_at}.\"\n                    )\n\n            if \"stop_duration\" in prot and \"stop_duration_candles\" in prot:\n                raise ConfigurationError(\n                    \"Protections must specify either `stop_duration` or `stop_duration_candles`.\\n\"\n                    f\"Please fix the protection {prot.get('method')}.\"\n                )\n\n            if \"lookback_period\" in prot and \"lookback_period_candles\" in prot:\n                raise ConfigurationError(\n                    \"Protections must specify either `lookback_period` or \"\n                    f\"`lookback_period_candles`.\\n Please fix the protection {prot.get('method')}.\"\n                )\n\n            if parsed_unlock_at is not None and (\n                \"stop_duration\" in prot or \"stop_duration_candles\" in prot\n            ):\n                raise ConfigurationError(\n                    \"Protections must specify either `unlock_at`, `stop_duration` or \"\n                    \"`stop_duration_candles`.\\n\"\n                    f\"Please fix the protection {prot.get('method')}.\"\n                )\n","sourceCodeStart":103,"sourceCodeEnd":126,"githubUrl":"https://github.com/freqtrade/freqtrade/blob/1c8edfe4d1e8d11bd4b40e8fc3237c26c3a60e15/freqtrade/plugins/protectionmanager.py#L103-L126","documentation":"`unlock_at` (a fixed daily UTC clock time) is mutually exclusive with `stop_duration`/`stop_duration_candles` (relative lock durations). A protection that sets `unlock_at` plus either duration key is rejected because the unlock rule would be ambiguous.","triggerScenarios":"A protection dict like {\"method\": \"StoplossGuard\", \"unlock_at\": \"04:00\", \"stop_duration\": 30} (or with `stop_duration_candles`).","commonSituations":"Trying to cap a duration-based lock with a daily unlock time; merging protection snippets from different sources.","solutions":["Use `unlock_at` alone for a daily clock-time unlock, or use only `stop_duration`/`stop_duration_candles` for a relative duration — remove the extra key(s)."],"exampleFix":"// before\n{\"method\": \"StoplossGuard\", \"unlock_at\": \"04:00\", \"stop_duration\": 30}\n// after\n{\"method\": \"StoplossGuard\", \"unlock_at\": \"04:00\"}","handlingStrategy":"validation","validationCode":"for prot in config.get('protections', []):\n    if 'unlock_at' in prot:\n        assert 'stop_duration' not in prot and 'stop_duration_candles' not in prot, \\\n            'unlock_at is mutually exclusive with stop_duration/stop_duration_candles'","typeGuard":"def protection_unlock_ok(prot: dict) -> bool:\n    return 'unlock_at' not in prot or ('stop_duration' not in prot and 'stop_duration_candles' not in prot)","tryCatchPattern":null,"preventionTips":["Remember unlock_at = absolute daily clock time; durations = relative. Pick one mental model per protection."],"tags":["freqtrade","protections","configuration","validation"],"backgroundTag":null,"analyzedSha":"1c8edfe4d1e8d11bd4b40e8fc3237c26c3a60e15","analyzedAt":"2026-08-15T05:09:08.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}