Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

VNish: MiningModeConfig.from_vnish() always returns MiningModeNormal, breaking set_power_limit() for all VNish miners #430

Description

@ubarenroom

Description

VNish.set_power_limit() (and more generally any code relying on MinerConfig.from_vnish().mining_mode being a MiningModePreset) never works for VNish firmware in preset/overclock mode, because MiningModeConfig.from_vnish() never actually returns a MiningModePreset instance — it always falls back to MiningModeNormal.

Root cause

In pyasic/config/mining/__init__.py:

@classmethod
def from_vnish(
    cls, web_settings: dict, web_presets: list[dict], web_perf_summary: dict
) -> MiningModeConfig:
    try:
        mode_settings = web_settings["miner"]["overclock"]
    except KeyError:
        return cls.default()

    if mode_settings["preset"] == "disabled":
        return cls.manual.from_vnish(mode_settings, web_presets, web_perf_summary)
    else:
        return cls.preset.from_vnish(mode_settings, web_presets, web_perf_summary)

MiningModeConfig is an Enum (subclass of MinerConfigOption), and cls.preset / cls.manual are enum members whose .value is the actual config class (MiningModePreset / MiningModeManual). They are not the classes themselves.

Because from_vnish is defined as a @classmethod on MiningModeConfig, accessing .from_vnish on an enum member resolves back to MiningModeConfig.from_vnish (bound to MiningModeConfig, not to MiningModePreset/MiningModeManual). So cls.preset.from_vnish(mode_settings, web_presets, web_perf_summary) actually calls MiningModeConfig.from_vnish(mode_settings, web_presets, web_perf_summary) recursively, this time with mode_settings (the overclock dict) passed as web_settings.

Inside that recursive call, web_settings["miner"] (i.e. mode_settings["miner"]) raises KeyError (the overclock dict has no "miner" key), which is caught and returns cls.default()MiningModeNormal().

Net effect: MiningModeConfig.from_vnish() always returns MiningModeNormal for VNish miners in preset mode (and likely also in manual/"disabled" mode, same bug via cls.manual.from_vnish).

Impact

VNishFirmware/VNish.set_power_limit() does:

if not isinstance(config.mining_mode, MiningModePreset):
    return False

This is always True (mining_mode is always MiningModeNormal), so set_power_limit() always returns False, regardless of whether any presets are tuned. Any downstream caller that treats False as failure (e.g. Home Assistant's miner integration number.antminer_power_limit) raises an error (Failed to set wattage.) on every attempt, on every VNish miner.

Reproduction

miner = await get_miner("<vnish-ip>")
config = await miner.get_config()
print(type(config.mining_mode))  # always <class 'pyasic.config.mining.MiningModeNormal'>

result = await miner.set_power_limit(2050)  # any wattage
print(result)  # always False

Suggested fix

Use .value to get the actual class before calling from_vnish:

if mode_settings["preset"] == "disabled":
    return cls.manual.value.from_vnish(mode_settings, web_presets, web_perf_summary)
else:
    return cls.preset.value.from_vnish(mode_settings, web_presets, web_perf_summary)

I verified locally that MiningModeConfig.preset.value.from_vnish(mode_settings, web_presets, web_perf_summary) correctly returns a MiningModePreset instance with available_presets populated and tuned/power parsed correctly, and that set_power_limit() then behaves as intended.

Environment

  • pyasic 0.79.0 (also present on master)
  • Miner: Antminer S19k Pro running VNish firmware
  • Python 3.14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions