You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Predbat randomly exports instead of freeze export, often in the peak rate #4453
Describe the bug
I am on a flat 12p export rate. Daily solar is more than I need, and I have more than enough battery capacity (in summer) to see me through the night.
Therefore an optimal plan is freeze export most of the solar day, with occasional demand periods when SoC drops every few days.
This optimal plan is what predbat produces but quite frequently it changes the plan and puts in an export, and the export is almost always in the peak import rate period, so impacting future Octopus Saving Session revenue.
Expected behaviour
Keep to the original plan of Freeze export
Predbat version
8.46.11
Environment details
HAOS HA 2026.7.4
2x gen 1 givenergy hybrid inverters, 1x AC3, each inverter with its own battery
Screenshots
I noticed Predbat was exporting at 17:40 so turned debug mode on to capture the log. Predbat seemed to hang and wasn't responding so I restarted the addon, when it restarted it then planned split slots, slow rate export in the current and next slot, and demand in the next slot. So as well as the unnecessary export, Demand in the first part of the 18:00 slot would just be incurring unnecessary conversion losses by charging and then discharging the battery
Plan after the restart
Predbat status showing the change from freeze exporting to exporting,and then the addon being restarted
I don't think this is relevant to the export issue, maybe to the 'hung and not responding' issue, but the logfile shows predbat didn't restart cleanly
I think I may have restarted the addon again and this time it came back OK and I could set a force freeze exporting
As I said, predbat does this frequently in the peak period, I'm wondering if the peak import rate causes it to think that exporting is more valuable (which it isn't)
Some additional information/example and an additional wrinkle/bug I encountered
This morning found predbat was planning a number of exports and demand slots in amongst the freeze exports, no real benefit in doing this and extra battery churn/loss
Turned debug mode on to capture the log, and predbat plan changed to demand then freeze export
later on (debug off) similar pattern
There appears to be an issue that turning debug mode on causes the plan to change, and change quite significantly
For the record - predbat was actively logging at the point you restarted it - It does not look like it was in an infinite loop, it was just busy - but debug does force it to use the python kernel and the is way slower than c++, and you have quite a complex system generating a huge amount of spew.
For the record - predbat was actively logging at the point you restarted it - It does not look like it was in an infinite loop, it was just busy - but debug does force it to use the python kernel and the is way slower than c++, and you have quite a complex system generating a huge amount of spew.
Thanks, useful to know about debug mode and python kernel. I’m running predbat on a mac m4 mini and its usually very responsive, and since it wasn’t loading the web console nor responding I assumed it had stopped.
On the debug-vs-no-debug plan difference specifically - dug into the mechanism and ran a direct test against your data.
Why it happens: kernel_supported() in prediction_kernel.py is gated on not debug_enable - turning debug on routes every scenario through the Python engine instead of the C++ kernel for as long as it's on. That alone doesn't explain a different plan though - the kernel and Python engine are tightly parity-tested to agree to 1e-6 on identical inputs. The actual cause is a second effect: the optimizer's coarse search pass (enable_fast_mode_levels, on by default, nothing to do with debug) requests a coarser time step to keep the search fast. The kernel silently ignores that and always computes at full 5-minute resolution internally (cheap enough in C++ to just always do it regardless); the Python fallback genuinely honours the coarser step, aggregating PV/load into bigger time buckets before simulating. So in normal (kernel) operation the "fast" pass is secretly exact; in debug mode it's genuinely coarser. On a flat/near-flat rate period, where many different battery decisions cost almost the same, that's enough to tip which near-tied option the search lands on.
Tested directly against your first debug.yaml (17:45:00 capture from the original report): replayed the same captured state twice through the real optimizer, changing only debug_enable, nothing else. Deterministic and repeatable both ways:
4 of 9 export windows in the 48h plan landed on different SoC targets between the two runs
Overall plan cost: kernel -1605.0281p vs debug -1605.0225p - a 0.0056p difference on ~1605p total (if anything, kernel was marginally the cheaper of the two)
The windows that differed were all >24h out in the forecast horizon, not the slot you were watching live at the time
Recomputing fresh from that 17:45 snapshot, kernel and debug both agreed the immediate window should be frozen, not exported
So as far as we can tell, neither plan looks "bad" - they're both close to optimal by Predbat's own cost model, just two equally-scored answers to a near-tie. Separately, I checked whether a known future Octopus Saving Session or Axle event was loaded at the time of the original decision (which would make draining the battery then a genuine mistake, not just a coin-flip) - it wasn't; the only saving-session/Axle data present in that snapshot was for already-past dates, so there was nothing upcoming for Predbat to have protected against at that moment.
Given that, I want to make sure I'm not missing what specifically feels "wrong" here beyond the debug/no-debug mismatch itself, which - per the above - looks like two valid, similarly-priced plans rather than one right and one wrong. If there's something else you'd still call a bug rather than "harmless churn" - the demand slots landing where they do, battery wear from the extra cycling, something in the newer debug.yaml set from this morning - could you spell that out again? Happy to dig into the 07:15-09:05 captures the same way if that's a distinct case worth checking separately.
Adding a data point that may be the same root cause, seen on different hardware (Fox ESS H1-G2-6.0-Wl, not GivEnergy), Predbat v8.47.7, on Octopus Intelligent Octopus Go (fixed 6.9p off-peak 23:30-05:30, 30.27p standard rate, 12p flat export).
Like the OP, I'm seeing the plan discharge/export well beyond what house load or a sensible pre-cheap-window taper would need, specifically during the standard/peak-rate (30.27p) evening period — and it's costing me an unplanned peak-rate import later to bridge the gap to the next cheap window.
Example (Saturday, actual/historical, not forecast):
Sat 20:30 30.27p SoC 70%
Sat 21:00 30.27p SoC 60% cost -31p
Sat 21:30 30.27p SoC 28% cost -15p
Sat 22:00 30.27p SoC 10% cost +12p <- min SoC hit, now importing
Sat 22:30 30.27p SoC 10% cost +12p
Sat 23:00 30.27p SoC 10% cost +9p
Sat 23:30 6.90p SoC 10%→ Chrg (cheap window opens)
A 10-point SoC drop on ~0.38kWh load should be worth roughly 11-12p in avoided import (self-consumption), not -31p — the extra is only explained by force-exporting well beyond load, at 12p, during a period where avoiding 30.27p import would have been strictly better for every kWh discharged. This then leaves the battery empty an hour-plus before the cheap window, forcing exactly the kind of unplanned peak-rate import the OP flags.
Same shape repeated on the following two nights (Sun→Mon, Mon→Tue) since updating to 8.47.7 — this wasn't happening before the update. One night was clean after an unrelated IOG slot reallocation earlier that day, so it's not literally every night, but frequent enough to be a clear regression rather than an edge case.
Supports the OP's hypothesis that the peak/standard import rate itself may be causing Predbat to overvalue export relative to self-consumption during that window.
Replayed the attached debug.yaml (predbat_debug.yaml-5.txt, 2026-08-11 08:50 capture) against current main - can't reproduce.
The plan for that day shows sensible behaviour throughout: FrzExp then Demand from 08:50-13:00 (SoC rises 49%->100% via solar surplus, not grid import, holds steady at 100%), then the only export in the whole day is a legitimate Exp at 18:00 for 14.00p - a genuine high evening peak rate. No unexplained low-rate export anywhere.
This doesn't confirm why the original screenshot happened, or pin down which specific fix (if any) resolved it - just that replaying the same captured inputs against current code no longer shows the reported symptom. We've been tinkering with freeze-export modelling this session (#4207/#4582), so it's plausible that's related, but not confirmed. Given it's not reproducing, happy to close if you agree - otherwise let us know if it recurs and we'll take another look.
Given there have been code changes since this occurred I will close this. The points about the plan being potentially different for debug and non debug mode is interesting, perhaps something for the FAQ's?
Activity
gcoan commentedon Aug 7, 2026
Some additional information/example and an additional wrinkle/bug I encountered
This morning found predbat was planning a number of exports and demand slots in amongst the freeze exports, no real benefit in doing this and extra battery churn/loss
Turned debug mode on to capture the log, and predbat plan changed to demand then freeze export
later on (debug off) similar pattern
There appears to be an issue that turning debug mode on causes the plan to change, and change quite significantly
with debug mode off
predbat_debug.yaml-2.txt
turn debug mode on
predbat_debug.yaml-3.txt
turn debug mode off
predbat_debug.yaml-4.txt
log files through this period
predbat.2.log
predbat.1.log
predbat.log
and debug files I captured:
predbat_debug_09_05_00.txt
predbat_debug_08_50_00.txt
predbat_debug_08_45_00.yaml
predbat_debug_08_40_00.yaml
predbat_debug_07_20_00.yaml
predbat_debug_07_15_00.txt
so two issues:
chalfontchubby commentedon Aug 7, 2026
For the record - predbat was actively logging at the point you restarted it - It does not look like it was in an infinite loop, it was just busy - but debug does force it to use the python kernel and the is way slower than c++, and you have quite a complex system generating a huge amount of spew.
gcoan commentedon Aug 8, 2026
Thanks, useful to know about debug mode and python kernel. I’m running predbat on a mac m4 mini and its usually very responsive, and since it wasn’t loading the web console nor responding I assumed it had stopped.
chalfontchubby commentedon Aug 8, 2026
On the debug-vs-no-debug plan difference specifically - dug into the mechanism and ran a direct test against your data.
Why it happens:
kernel_supported()inprediction_kernel.pyis gated onnot debug_enable- turning debug on routes every scenario through the Python engine instead of the C++ kernel for as long as it's on. That alone doesn't explain a different plan though - the kernel and Python engine are tightly parity-tested to agree to 1e-6 on identical inputs. The actual cause is a second effect: the optimizer's coarse search pass (enable_fast_mode_levels, on by default, nothing to do with debug) requests a coarser time step to keep the search fast. The kernel silently ignores that and always computes at full 5-minute resolution internally (cheap enough in C++ to just always do it regardless); the Python fallback genuinely honours the coarser step, aggregating PV/load into bigger time buckets before simulating. So in normal (kernel) operation the "fast" pass is secretly exact; in debug mode it's genuinely coarser. On a flat/near-flat rate period, where many different battery decisions cost almost the same, that's enough to tip which near-tied option the search lands on.Tested directly against your first debug.yaml (17:45:00 capture from the original report): replayed the same captured state twice through the real optimizer, changing only
debug_enable, nothing else. Deterministic and repeatable both ways:-1605.0281pvs debug-1605.0225p- a 0.0056p difference on ~1605p total (if anything, kernel was marginally the cheaper of the two)So as far as we can tell, neither plan looks "bad" - they're both close to optimal by Predbat's own cost model, just two equally-scored answers to a near-tie. Separately, I checked whether a known future Octopus Saving Session or Axle event was loaded at the time of the original decision (which would make draining the battery then a genuine mistake, not just a coin-flip) - it wasn't; the only saving-session/Axle data present in that snapshot was for already-past dates, so there was nothing upcoming for Predbat to have protected against at that moment.
Given that, I want to make sure I'm not missing what specifically feels "wrong" here beyond the debug/no-debug mismatch itself, which - per the above - looks like two valid, similarly-priced plans rather than one right and one wrong. If there's something else you'd still call a bug rather than "harmless churn" - the demand slots landing where they do, battery wear from the extra cycling, something in the newer debug.yaml set from this morning - could you spell that out again? Happy to dig into the 07:15-09:05 captures the same way if that's a distinct case worth checking separately.
jHamshaw commentedon Aug 9, 2026
Adding a data point that may be the same root cause, seen on different hardware (Fox ESS H1-G2-6.0-Wl, not GivEnergy), Predbat v8.47.7, on Octopus Intelligent Octopus Go (fixed 6.9p off-peak 23:30-05:30, 30.27p standard rate, 12p flat export).
Like the OP, I'm seeing the plan discharge/export well beyond what house load or a sensible pre-cheap-window taper would need, specifically during the standard/peak-rate (30.27p) evening period — and it's costing me an unplanned peak-rate import later to bridge the gap to the next cheap window.
Example (Saturday, actual/historical, not forecast):
Sat 20:30 30.27p SoC 70%
Sat 21:00 30.27p SoC 60% cost -31p
Sat 21:30 30.27p SoC 28% cost -15p
Sat 22:00 30.27p SoC 10% cost +12p <- min SoC hit, now importing
Sat 22:30 30.27p SoC 10% cost +12p
Sat 23:00 30.27p SoC 10% cost +9p
Sat 23:30 6.90p SoC 10%→ Chrg (cheap window opens)
A 10-point SoC drop on ~0.38kWh load should be worth roughly 11-12p in avoided import (self-consumption), not -31p — the extra is only explained by force-exporting well beyond load, at 12p, during a period where avoiding 30.27p import would have been strictly better for every kWh discharged. This then leaves the battery empty an hour-plus before the cheap window, forcing exactly the kind of unplanned peak-rate import the OP flags.
Same shape repeated on the following two nights (Sun→Mon, Mon→Tue) since updating to 8.47.7 — this wasn't happening before the update. One night was clean after an unrelated IOG slot reallocation earlier that day, so it's not literally every night, but frequent enough to be a clear regression rather than an edge case.
Supports the OP's hypothesis that the peak/standard import rate itself may be causing Predbat to overvalue export relative to self-consumption during that window.
predbat_debug.yaml.txt
fix(debug): auto-disable debug_enable after 2 hours instead of unboun…
gcoan commentedon Aug 11, 2026
Another example this morning, can't see an obvious reason why predbat will let the battery charge in demand mode and then export stored charge?
predbat.log
predbat_debug.yaml-5.txt
fix(plan): clip phantom export off, not to freeze, when SoC is pinned…
fix(plan): convert phantom export windows to freeze in clip_export_sl…
refactor(plan): drop the clip removal branches now subsumed by the prune
feat(plan): model-based clipping — prune plan slots that are dead in …
fix(debug): auto-disable debug_enable after 2 hours instead of unboun…
chalfontchubby commentedon Aug 20, 2026
Replayed the attached debug.yaml (predbat_debug.yaml-5.txt, 2026-08-11 08:50 capture) against current main - can't reproduce.
The plan for that day shows sensible behaviour throughout:
FrzExpthenDemandfrom 08:50-13:00 (SoC rises 49%->100% via solar surplus, not grid import, holds steady at 100%), then the only export in the whole day is a legitimateExpat 18:00 for 14.00p - a genuine high evening peak rate. No unexplained low-rate export anywhere.This doesn't confirm why the original screenshot happened, or pin down which specific fix (if any) resolved it - just that replaying the same captured inputs against current code no longer shows the reported symptom. We've been tinkering with freeze-export modelling this session (#4207/#4582), so it's plausible that's related, but not confirmed. Given it's not reproducing, happy to close if you agree - otherwise let us know if it recurs and we'll take another look.
jHamshaw commentedon Aug 21, 2026
Given the rapid pace of change this week I've been monitoring thsi and from my perspective it appears to have been resolved...
gcoan commentedon Aug 29, 2026
Given there have been code changes since this occurred I will close this. The points about the plan being potentially different for debug and non debug mode is interesting, perhaps something for the FAQ's?