Skip to content

rate_add_io_slots: zero-kWh exemption can't distinguish malformed SMART input from a genuine zero-kWh event #4807

Open

Description

@chalfontchubby

Follow-up from review on #4483 (raised by @Speshman, comment #4483 (comment)).

decode_octopus_slot() silently coerces an invalid/unparseable charge_in_kwh value to 0.0. rate_add_io_slots()'s zero-kWh exemption (octopus.py, zero_kwh_exempt = (kwh <= 0) and (source == "SMART") and not self.octopus_slot_count_zero_kwh) was scoped to source == "SMART" to narrow this, but a malformed entry that happens to also carry source == "SMART" is still indistinguishable from a genuine zero-kWh SMART grid-flex event and gets the same exemption from both the octopus_slot_max cap and the #4482 "does the car still need this" check.

Proposed fix: thread a parse-success flag through decode_octopus_slot()'s return (rather than coercing failures to a bare 0.0) and require it in the exemption condition, so a parse failure never qualifies regardless of source.

Scope: contained to octopus.py's decode_octopus_slot()/rate_add_io_slots() plus one new test in tests/test_rate_add_io_slots.py (a malformed-charge_in_kwh + source=="SMART" case). Follow-up PR to stack on #4483.

Activity

  1. springfall2008 commented on Aug 28, 2026

    @springfall2008
    Owner

    🤖 Automated first-pass triage — a maintainer will review before any action is taken.

    Classification: bug (in not-yet-merged code) · Priority: priority_low

    Context confirmed: this is a real, self-contained defect, but it lives in the still-open PR #4483 (fix/iog-limit-future-slots-by-ev-soc), not on current main — main at c2135caa (v8.53.5-10-gc2135caa) has decode_octopus_slot()/rate_add_io_slots() but no zero_kwh_exempt/octopus_slot_count_zero_kwh at all; that logic only exists on the PR branch. This is 1 of 3 follow-up issues (alongside #4808, #4809) that PR's author (@chalfontchubby) filed for themself per the review thread's closing comment, tracking points @Speshman raised in review that were deliberately deferred rather than block the merge. No duplicates found.

    Verified the mechanism described: on the PR branch, octopus.py's decode_octopus_slot() (current main equivalent at apps/predbat/octopus.py:2867-2870) does:

    try:
        kwh = abs(float(kwh))
    except (ValueError, TypeError):
        kwh = 0.0

    — a malformed/unparseable charge_in_kwh and a genuine zero-kWh reading are indistinguishable by the time rate_add_io_slots() sees them. The PR's zero_kwh_exempt = (kwh <= 0) and (source == "SMART") and not self.octopus_slot_count_zero_kwh (added in response to an earlier review round) narrows this to source == "SMART", but as the issue notes, a malformed entry that happens to also carry that source still passes.

    On the proposed fix: threading a parse-success flag through decode_octopus_slot()'s return is sound and low-risk — both call sites (octopus.py:2896 in load_octopus_slots(), and octopus.py:3054 in rate_add_io_slots(), using raw=True) already unpack a 5-tuple positionally, so adding a 6th value is a mechanical change at both. No test to run here — the affected code (zero_kwh_exempt) doesn't exist on main yet, so nothing in TEST_REGISTRY currently exercises it; the new coverage described (a malformed-charge_in_kwh + source=="SMART" test in tests/test_rate_add_io_slots.py) will need to land alongside the fix, stacked on #4483.

    Bug report template check: not applicable — this isn't a user bug report (no version/environment/log/debug-yaml expected or needed).

    Labelled bug (a genuine logic defect, scoped small) and priority_low (not yet in any merged/released code, requires a rare malformed-input-plus-source=="SMART" combination, and is already a tightly scoped, pre-agreed follow-up with an implementation path).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions