Describe the bug
On an Alfen Eve Single Pro (OCPP 1.6J, single connector), evcc occasionally persists a charging session with:
- meterStart: null
- chargedEnergy ≈ the wallbox's lifetime Energy.Active.Import.Register reading (several thousand kWh)
As a result, all aggregated statistics (daily/monthly/yearly totals, cost, CO₂) become unusable because a single session contributes ~8 MWh.
This has happened three times in four weeks. The installation was switched from Modbus to OCPP four weeks ago; under Modbus the same wallbox never produced corrupt session data.
Affected sessions (GET /api/sessions):
id created chargedEnergy (kWh) meterStart meterStop
367 2026-03-30 09:38 7 783.903 null 7 783.903
380 2026-04-02 12:51 7 825.248 null 7 825.248
409 2026-04-23 09:17 7 930.179 null 7 912.760
Current lifetime Energy.Active.Import.Register of the wallbox at the time of writing: 7 930 237 Wh — i.e. all three corrupted chargedEnergy values match the wallbox's absolute lifetime meter reading at the time the session ended.
Note for id 409: chargedEnergy (7930.179) > meterStop (7912.760) — so chargedEnergy is not simply meterStop − 0; it comes from a different accumulation path.
Two parallel meter series in the DB
Across 400+ sessions there are two independently growing meter series in meterStart/meterStop. The OCPP trace only ever shows one Energy.Active.Import.Register stream (single measurand, location: "Outlet", no duplicates), which grows around the ~7 900 kWh mark. The second series around ~4 900 kWh does not appear in any OCPP frame — evcc seems to accumulate it internally (likely from Power.Active.Import × Δt) and then writes it into the same session fields as the real meter reading. Example (sessions 371–378, in chronological order):
id=371 meterStart=4944.257 meterStop=4944.356 # internal series
id=372 meterStart=7786.260 meterStop=7793.713 # Alfen meter
id=374 meterStart=7793.969 meterStop=7794.487 # Alfen meter
id=375 meterStart=4944.372 meterStop=4950.589 # internal series
id=376 meterStart=7794.723 meterStop=7809.332 # Alfen meter
id=377 meterStart=4963.570 meterStop=4963.921 # internal series
id=378 meterStart=7809.332 meterStop=null # Alfen meter, StopTransaction lost
Both series progress monotonically for months, so evcc is clearly persisting two different sources into the same columns without distinguishing their origin.
Also: out of 392 sessions, 16 (~4 %) have at least one null meter field, and the frequency is growing over time.
Suspected trigger: startup measurand probing rewrites MeterValuesSampledData
The OCPP trace at startup shows evcc sending seven sequential ChangeConfiguration requests that each overwrite the charger's entire MeterValuesSampledData with a single measurand, and only at the end restores the full list:
send ChangeConfiguration MeterValuesSampledData=Power.Active.Import
send ChangeConfiguration MeterValuesSampledData=Energy.Active.Import.Register
send ChangeConfiguration MeterValuesSampledData=Current.Import
send ChangeConfiguration MeterValuesSampledData=Voltage
send ChangeConfiguration MeterValuesSampledData=Current.Offered
send ChangeConfiguration MeterValuesSampledData=Power.Offered
send ChangeConfiguration MeterValuesSampledData=SoC
send ChangeConfiguration MeterValuesSampledData=Power.Active.Import,Energy.Active.Import.Register,Current.Import,Voltage,Current.Offered
Before this probing starts, the charger already reports its MeterValuesSampledData correctly configured as Power.Active.Import,Energy.Active.Import.Register,Current.Import,Voltage,Current.Offered in GetConfiguration. The probing is therefore unnecessary, and during the window in which MeterValuesSampledData is transiently set to e.g. only SoC or Power.Offered, any MeterValues the charger sends contains no Energy.Active.Import.Register.
If a session's StartTransaction (or the first subsequent MeterValues) falls into that window, evcc gets no valid meter reading to use as meterStart. On StopTransaction the charger then delivers the lifetime Energy.Active.Import.Register reading (as required by its StopTxnSampledData=Energy.Active.Import.Register configuration), and evcc appears to store that lifetime value as chargedEnergy / meterStop without validating that a valid meterStart was captured.
Expected behavior
- evcc should not clobber MeterValuesSampledData at startup when the charger already reports the desired -measurands as configured. If probing is still needed, it should either
-- try the full list in one request and fall back measurand-by-measurand only on Rejected, or
-- restore the original configured list immediately after each probe, or
-- be skipped entirely when GetConfiguration shows the desired measurands are already present.
- If meterStart for a session cannot be determined, chargedEnergy must be computed strictly from Power × Δt (bounded by session duration × max charger power), never from an absolute meter reading.
- Per charger, evcc should use a single, well-defined meter source (OCPP meter or internal integration) so both cannot end up in the same meterStart/meterStop columns.
- A sanity check before persisting — e.g. chargedEnergy ≤ connectorMaxPower × sessionDuration × 1.1 and < 300 kWh for a single AC session — would have prevented all three catastrophic records here.
Steps to reproduce
Not reliably reproducible on demand. The pattern over 400+ sessions is:
- Run evcc against an Alfen Eve Single Pro over OCPP 1.6J, with the default Power.Active.Import,Energy.Active.Import.Register,Current.Import,Voltage,Current.Offered measurand set.
- Restart evcc (e.g. docker image update) occasionally.
- After some number of restarts, a session is persisted with meterStart: null and chargedEnergy ≈ the wallbox's lifetime meter reading.
Configuration details
Configuration is done entirely through the evcc web UI (native OCPP integration). No custom evcc.yaml overrides for the charger. The charger is a single OCPP charge point at connector 1, meterinterval: 10s, default measurands. One loadpoint in pv mode.
Log details
Excerpt of the startup trace showing the probing behaviour and a subsequent normal MeterValues frame (identifying fields redacted):
text
[ocpp] TRACE recv: [3,"…",{"configurationKey":[
… ,
{"key":"MeterValuesAlignedData","readonly":false,"value":""},
{"key":"MeterValueSampleInterval","readonly":false,"value":"10"},
{"key":"MeterValuesSampledData","readonly":false,
"value":"Power.Active.Import,Energy.Active.Import.Register,Current.Import,Voltage,Current.Offered"},
{"key":"StopTxnSampledData","readonly":false,"value":"Energy.Active.Import.Register"},
{"key":"StopTxnAlignedData","readonly":false,"value":"Energy.Active.Import.Register"},
{"key":"MeterValuesSampledDataMaxLength","readonly":true,"value":"9"},
{"key":"OCPPStackVersion","readonly":true,"value":"7.1"},
…
]}]
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Power.Active.Import
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Energy.Active.Import.Register
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Current.Import
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Voltage
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Current.Offered
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Power.Offered
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=SoC
[ocpp] TRACE send: ChangeConfiguration MeterValuesSampledData=Power.Active.Import,Energy.Active.Import.Register,Current.Import,Voltage,Current.Offered
[ocpp] TRACE recv: MeterValues
{"timestamp":"2026-04-23T19:46:21Z","sampledValue":[
{"value":"0.000", "measurand":"Power.Active.Import", "location":"Outlet","unit":"W"},
{"value":"7930237.000","measurand":"Energy.Active.Import.Register", "location":"Outlet","unit":"Wh"},
{"value":"0.000", "measurand":"Current.Import","phase":"L1", "location":"Outlet","unit":"A"},
{"value":"0.000", "measurand":"Current.Import","phase":"L2", "location":"Outlet","unit":"A"},
{"value":"0.000", "measurand":"Current.Import","phase":"L3", "location":"Outlet","unit":"A"},
{"value":"239.470", "measurand":"Voltage","phase":"L1-N", "location":"Outlet","unit":"V"},
{"value":"241.990", "measurand":"Voltage","phase":"L2-N", "location":"Outlet","unit":"V"},
{"value":"240.560", "measurand":"Voltage","phase":"L3-N", "location":"Outlet","unit":"V"},
{"value":"0.000", "measurand":"Current.Offered", "location":"Outlet","unit":"A"}
]}
The charger therefore reports a single, well-formed Energy.Active.Import.Register (single measurand, location: "Outlet", no phase, no duplicates) and already has the correct MeterValuesSampledData list configured before evcc starts probing.
I can provide the full trace (including the StartTransaction / StopTransaction for the next corrupt session) on request.
What type of operating system or environment does evcc run on?
Linux
External automation
Nightly build
Version
0.305.1
Describe the bug
On an Alfen Eve Single Pro (OCPP 1.6J, single connector), evcc occasionally persists a charging session with:
As a result, all aggregated statistics (daily/monthly/yearly totals, cost, CO₂) become unusable because a single session contributes ~8 MWh.
This has happened three times in four weeks. The installation was switched from Modbus to OCPP four weeks ago; under Modbus the same wallbox never produced corrupt session data.
Affected sessions (GET /api/sessions):
Current lifetime Energy.Active.Import.Register of the wallbox at the time of writing: 7 930 237 Wh — i.e. all three corrupted chargedEnergy values match the wallbox's absolute lifetime meter reading at the time the session ended.
Note for id 409: chargedEnergy (7930.179) > meterStop (7912.760) — so chargedEnergy is not simply meterStop − 0; it comes from a different accumulation path.
Two parallel meter series in the DB
Across 400+ sessions there are two independently growing meter series in meterStart/meterStop. The OCPP trace only ever shows one Energy.Active.Import.Register stream (single measurand, location: "Outlet", no duplicates), which grows around the ~7 900 kWh mark. The second series around ~4 900 kWh does not appear in any OCPP frame — evcc seems to accumulate it internally (likely from Power.Active.Import × Δt) and then writes it into the same session fields as the real meter reading. Example (sessions 371–378, in chronological order):
Both series progress monotonically for months, so evcc is clearly persisting two different sources into the same columns without distinguishing their origin.
Also: out of 392 sessions, 16 (~4 %) have at least one null meter field, and the frequency is growing over time.
Suspected trigger: startup measurand probing rewrites MeterValuesSampledData
The OCPP trace at startup shows evcc sending seven sequential ChangeConfiguration requests that each overwrite the charger's entire MeterValuesSampledData with a single measurand, and only at the end restores the full list:
Before this probing starts, the charger already reports its MeterValuesSampledData correctly configured as Power.Active.Import,Energy.Active.Import.Register,Current.Import,Voltage,Current.Offered in GetConfiguration. The probing is therefore unnecessary, and during the window in which MeterValuesSampledData is transiently set to e.g. only SoC or Power.Offered, any MeterValues the charger sends contains no Energy.Active.Import.Register.
If a session's StartTransaction (or the first subsequent MeterValues) falls into that window, evcc gets no valid meter reading to use as meterStart. On StopTransaction the charger then delivers the lifetime Energy.Active.Import.Register reading (as required by its StopTxnSampledData=Energy.Active.Import.Register configuration), and evcc appears to store that lifetime value as chargedEnergy / meterStop without validating that a valid meterStart was captured.
Expected behavior
-- try the full list in one request and fall back measurand-by-measurand only on Rejected, or
-- restore the original configured list immediately after each probe, or
-- be skipped entirely when GetConfiguration shows the desired measurands are already present.
Steps to reproduce
Not reliably reproducible on demand. The pattern over 400+ sessions is:
Configuration details
Log details
What type of operating system or environment does evcc run on?
Linux
External automation
Nightly build
Version
0.305.1