freqtrade/freqtrade · error · ConfigurationError

Protections must specify either `unlock_at`, `stop_duration`

Error message

Protections must specify either `unlock_at`, `stop_duration` or `stop_duration_candles`.\nPlease fix the protection {prot.get('method')}.

What it means

`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.

Source

Thrown at freqtrade/plugins/protectionmanager.py:121

                        f"Invalid date format for unlock_at: {config_unlock_at}."
                    )

            if "stop_duration" in prot and "stop_duration_candles" in prot:
                raise ConfigurationError(
                    "Protections must specify either `stop_duration` or `stop_duration_candles`.\n"
                    f"Please fix the protection {prot.get('method')}."
                )

            if "lookback_period" in prot and "lookback_period_candles" in prot:
                raise ConfigurationError(
                    "Protections must specify either `lookback_period` or "
                    f"`lookback_period_candles`.\n Please fix the protection {prot.get('method')}."
                )

            if parsed_unlock_at is not None and (
                "stop_duration" in prot or "stop_duration_candles" in prot
            ):
                raise ConfigurationError(
                    "Protections must specify either `unlock_at`, `stop_duration` or "
                    "`stop_duration_candles`.\n"
                    f"Please fix the protection {prot.get('method')}."
                )

View on GitHub (pinned to 1c8edfe4d1)

Solutions

  1. 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).

Example fix

// before
{"method": "StoplossGuard", "unlock_at": "04:00", "stop_duration": 30}
// after
{"method": "StoplossGuard", "unlock_at": "04:00"}
Defensive patterns

Strategy: validation

Validate before calling

for prot in config.get('protections', []):
    if 'unlock_at' in prot:
        assert 'stop_duration' not in prot and 'stop_duration_candles' not in prot, \
            'unlock_at is mutually exclusive with stop_duration/stop_duration_candles'

Type guard

def protection_unlock_ok(prot: dict) -> bool:
    return 'unlock_at' not in prot or ('stop_duration' not in prot and 'stop_duration_candles' not in prot)

Prevention

When it happens

Trigger: A protection dict like {"method": "StoplossGuard", "unlock_at": "04:00", "stop_duration": 30} (or with `stop_duration_candles`).

Common situations: Trying to cap a duration-based lock with a daily unlock time; merging protection snippets from different sources.

Related errors


AI-assisted analysis of freqtrade/freqtrade@1c8edfe4d1 (2026-08-15). Data as JSON: /api/errors/5d4e55780852e68a. Report an issue: GitHub.