PHP2Shell alert: critical PHP flaws CVE-2026-109618 / 109619 — check your servers and get patched fast
HashTech Systems
EV Charging
Part 3 of 12

OCPP 1.6 StatusNotification: Connector Status and Error Codes

The OCPP 1.6 connector status model: all nine ChargePointStatus values, connectorId 0, error codes, valid transitions and how a CSMS should use them.

HashTech Engineering · October 26, 2026 · 6 min read

StatusNotification is how a charger tells the CSMS what each connector is doing: free, in use, faulted, reserved or out of service. It drives the availability shown in driver apps, the status you publish to roaming partners, and most of your fault alerting. This is part 3 of the series; part 2 covered boot and heartbeat.

The message

json
[
  2,
  "st-4471",
  "StatusNotification",
  {
    "connectorId": 1,
    "errorCode": "NoError",
    "status": "Charging",
    "timestamp": "2026-10-26T09:31:47Z"
  }
]

The response is an empty object: [3, "st-4471", {}]. The CSMS has no way to reject a status. It records it.

FieldTypeRequiredNotes
connectorIdinteger, 0 or higherYes0 means the Charge Point as a whole
errorCodeChargePointErrorCodeYesNoError when nothing is wrong
statusChargePointStatusYesSee below
infoCiString50NoFree-text extra information
timestampdateTimeNoWhen the status was reported; use receive time if absent
vendorIdCiString255NoIdentifies the vendor-specific error code namespace
vendorErrorCodeCiString50NoVendor-specific error code

The nine status values

statusMeaning
AvailableConnector is free for a new user.
PreparingA user has started interacting (plugged in, presented a card, or a remote start arrived) but charging has not started.
ChargingContactor closed and the vehicle is charging.
SuspendedEVSETransaction is active but the charger is not offering energy, for example because a smart charging limit is 0.
SuspendedEVCharger offers energy but the vehicle is not taking it (battery full, vehicle schedule, vehicle-side pause).
FinishingTransaction has stopped but the connector is not yet free, typically because the cable is still plugged in.
ReservedConnector is reserved through ReserveNow.
UnavailableConnector is out of service, usually through ChangeAvailability to Inoperative.
FaultedConnector (or charger) has a fault and cannot be used.

The distinction between SuspendedEV and SuspendedEVSE matters operationally. SuspendedEV near the end of a session is normal; the vehicle is full. SuspendedEVSE that you did not cause through smart charging deserves investigation, and a SuspendedEVSE with a TxProfile limit of 0 is exactly what you should see when your load management pauses a session (see part 9).

connectorId 0

Connector 0 reports the status of the Charge Point as a whole. Only Available, Unavailable and Faulted are meaningful for it; a charger reporting connector 0 as Charging is not following the spec. A charger-wide fault (lost meter communication, internal error) usually appears as connector 0 Faulted, sometimes with every connector also reported Faulted, sometimes not.

When you calculate whether a connector is usable, combine both: a connector is usable only if neither it nor connector 0 is Unavailable or Faulted. Publishing connector 1 as available to an OCPI partner while connector 0 is faulted sends drivers to a dead charger. OCPP to OCPI mapping goes into that translation in detail.

Error codes

errorCode is independent of status. An error code other than NoError does not automatically mean Faulted. A charger might report Available with WeakSignal, or Charging with HighTemperature while it derates.

errorCodeTypical cause
ConnectorLockFailureCable lock failed to lock or unlock
EVCommunicationErrorCommunication with the vehicle failed (control pilot or, for DC, the charging protocol)
GroundFailureGround fault / residual current device tripped
HighTemperatureOver-temperature in the charger or connector
InternalErrorHardware or software failure inside the charger
LocalListConflictThe idTagInfo from the CSMS conflicts with the local authorization list
NoErrorNo error
OtherErrorAnything else; check vendorErrorCode and info
OverCurrentFailureVehicle drew more current than offered
OverVoltageSupply voltage too high
PowerMeterFailureMeter cannot be read
PowerSwitchFailureContactor/relay failed
ReaderFailureRFID reader failure
ResetFailureA Reset could not be performed
UnderVoltageSupply voltage too low
WeakSignalWeak wireless signal

In the field, a large share of faults arrive as OtherError or InternalError with the real information in vendorErrorCode and info. Keep a per-vendor lookup table of those codes, and record them verbatim. Over time this table becomes one of the most valuable pieces of operational knowledge you have; EV charger uptime and reliability covers how to turn it into alerts.

Transitions in a normal session

The 1.6 specification includes a table of allowed transitions between states. The common paths are:

text
Plug in, then authorize:
  Available -> Preparing -> Charging -> SuspendedEV -> Finishing -> Available

Authorize first, then plug in:
  Available -> Preparing -> Charging ...

Authorized but no cable connected within ConnectionTimeOut:
  Available -> Preparing -> Available

Reservation:
  Available -> Reserved -> Preparing -> Charging ...

Do not build a CSMS that refuses to process a status because the transition looks invalid. Chargers skip states (going straight from Available to Charging is common), send duplicates, and occasionally report states out of order because of queued messages. Record what you receive, use timestamp to order it, and alert on suspicious patterns instead of rejecting them.

Status and transactions are separate

A frequent CSMS mistake is to derive transaction state from status, or the reverse. A transaction starts with StartTransaction and ends with StopTransaction (part 5), and status is a parallel signal. You can see Finishing before StopTransaction arrives, Charging before you have a transactionId, and Available after a power cut with a transaction still open in your database. Keep two state machines and reconcile them, rather than merging them.

Flapping and MinimumStatusDuration

Some chargers report rapid status changes, for example toggling between Charging and SuspendedEV every few seconds as a vehicle balances cells. The optional MinimumStatusDuration configuration key sets how many seconds a status must be stable before the charger reports it, which reduces noise. Not every charger supports it, so also debounce on the CSMS side before pushing status updates to apps and roaming partners.

Offline gaps

When a charger has been offline, it may have gone through several states that you never saw. The 1.6 specification lets the charger send only the current status of each connector after it reconnects, rather than replaying every change, so your status history will have gaps. Do not compute availability or uptime metrics as if each transition was observed; treat an offline period as unknown, and mark it as such in reports. This matters for regulatory uptime reporting, where the difference between "offline" and "faulted" can be significant (see NEVI and AFIR requirements).

What to do with status in the CSMS

  • Store every notification with charger identity, connector, status, error code, vendor fields, charger timestamp and receive time.
  • Maintain a current-state view per connector (and connector 0), updated only when an incoming timestamp is newer than the stored one.
  • Alert on Faulted lasting longer than a threshold, on repeated faults on the same connector, and on chargers that report Unavailable without a matching ChangeAvailability from you.
  • Publish a debounced, combined status to apps and roaming partners, not the raw stream.

Getting the current status on demand

If you are unsure what state a connector is in, for example after a CSMS restart or a suspected missed message, ask for it with TriggerMessage (Remote Trigger profile):

json
[
  2,
  "csms-tr-12",
  "TriggerMessage",
  {
    "requestedMessage": "StatusNotification",
    "connectorId": 1
  }
]

The charger answers Accepted and then sends a fresh StatusNotification. Omitting connectorId asks for all connectors. Part 8 covers TriggerMessage in more depth.

Key takeaways

  • Nine statuses, sixteen error codes, and they are independent: a non-NoError code does not imply Faulted.
  • Connector 0 is the whole charger; combine it with per-connector status before publishing availability.
  • Record transitions as received, order by timestamp, and do not reject unexpected ones.
  • Keep status and transaction state as separate state machines.
  • Store vendorErrorCode and info; that is where the useful fault detail lives.

Previous: Part 2, BootNotification and Heartbeat. Next: Part 4, Authorize and id tags.

Let's Talk

Ready to build something that lasts?

Whether it's a charging network, an AI rollout, or a core enterprise system — let's talk about what you're building.