OCPP error codes are the standardized error responses defined by the Open Charge Point Protocol for communicating failures between charge points and the CSMS (Charging Station Management System). Understanding these errors is essential for every developer building, integrating, or debugging EV charging infrastructure.
When an OCPP message cannot be processed, the receiving party responds with a CALLERROR message containing a specific error code, a human-readable description, and optional error details. Misinterpreting these errors or failing to handle them correctly leads to stuck transactions, offline chargers, and frustrated drivers.
This guide covers every OCPP error code, their common causes, and how to resolve them.
How OCPP Error Handling Works
OCPP uses a simple request-response model over WebSocket. Every request (CALL) receives either a success response (CALLRESULT) or an error response (CALLERROR). There is no concept of partial success or warnings within the protocol itself.
The CALLERROR Message Format
A CALLERROR is a JSON array with message type 4:
[4, "messageId", "errorCode", "errorDescription", {errorDetails}]| Field | Type | Description |
|---|---|---|
4 |
Integer | Message type identifier for CALLERROR |
messageId |
String | Must match the messageId of the original CALL |
errorCode |
String | One of the standardized OCPP error codes |
errorDescription |
String | Human-readable error explanation (max 255 characters) |
errorDetails |
Object | Optional JSON object with additional error context |
Example CALLERROR Exchange
A charger sends an Authorize request:
[2, "auth-001", "Authorize", {
"idTag": "RFID-XYZ789"
}]The CSMS encounters an internal database failure and responds:
[4, "auth-001", "InternalError",
"Authorization service temporarily unavailable",
{"retryAfter": 30}]The messageId ("auth-001") matches the original request, identifying which CALL this error corresponds to. The errorDetails object can contain any additional information the sender deems useful, though its structure is not standardized.
Complete OCPP Error Code Reference
NotImplemented
Description: The requested action is not known by the receiver.
Common Causes:
- Sending an OCPP 2.0.1 action to a CSMS that only supports OCPP 1.6
- Typo in the action name (e.g., "BootNotification" vs "bootNotification" -- OCPP is case-sensitive)
- Custom or proprietary actions that the other party does not recognize
- Protocol version mismatch between charger and CSMS
How to Fix:
- Verify the action name matches the OCPP specification exactly, including casing
- Confirm both parties are using the same OCPP version
- Check the WebSocket subprotocol negotiation to ensure version agreement
- Review the CSMS or charger documentation for supported action lists
[4, "msg-001", "NotImplemented",
"Action 'DataTransfer' is not implemented",
{}]NotSupported
Description: The action is recognized but intentionally not supported by the receiver.
Common Causes:
- Sending
SetChargingProfileto a charger that does not support smart charging - Requesting
GetDiagnosticsfrom a charger without diagnostics capability - Using optional OCPP features that the implementation chose not to include
- Feature profile not enabled on the charger firmware
How to Fix:
- Check the charger's supported feature profiles in its documentation or configuration
- In OCPP 2.0.1, verify the device model's supported feature list
- Implement fallback logic for optional features that may not be universally supported
- Do not confuse with
NotImplemented--NotSupportedmeans the receiver knows the action but explicitly declines it
[4, "msg-002", "NotSupported",
"SetChargingProfile is not supported by this charge point",
{"supportedProfiles": ["Core", "FirmwareManagement"]}]InternalError
Description: An internal error occurred in the receiver that prevented processing the request.
Common Causes:
- Database connection failure on the CSMS
- Out-of-memory condition on the charge point
- Unhandled exception in the message processing logic
- Downstream service unavailable (payment gateway, authorization service)
- File system full on the charge point (preventing log or cache writes)
How to Fix:
- Check server/charger logs for the underlying exception or error
- Monitor system resources (CPU, memory, disk, database connections)
- Implement retry logic with exponential backoff on the calling side
- Ensure all downstream dependencies have health checks and circuit breakers
- This is a catch-all for server-side failures, so root cause analysis requires log inspection
[4, "msg-003", "InternalError",
"Database connection pool exhausted",
{"timestamp": "2025-02-08T14:30:00Z"}]ProtocolError
Description: The payload does not conform to the OCPP protocol specification.
Common Causes:
- Sending a CALLRESULT with the wrong payload structure for the action
- Message ID format violations
- Sending a response to a message ID that was never sent
- Incorrect message type identifier (e.g., using
2instead of3for a response) - Violating the OCPP requirement that only one CALL can be pending per direction
How to Fix:
- Validate all messages against the OCPP JSON schema before sending
- Ensure message IDs are correctly tracked and matched between CALL and CALLRESULT/CALLERROR
- Verify that your implementation does not send a new CALL before receiving the response to the previous one
- Use a protocol-level message validator in your development environment
[4, "msg-004", "ProtocolError",
"Received CALLRESULT for unknown messageId",
{"receivedMessageId": "unknown-123"}]SecurityError
Description: A security-related issue prevented processing the request.
Common Causes:
- Invalid or expired TLS client certificate
- HTTP Basic Auth credentials rejected
- Charge point identity does not match the certificate's Common Name
- Attempting to perform an action that requires higher security profile authorization
- Tampered message detected (in implementations using message signing)
How to Fix:
- Verify TLS certificate validity, chain completeness, and expiration dates
- Confirm HTTP Basic Auth credentials match the CSMS configuration
- Ensure the charge point's identity string matches across all security layers
- Check that the security profile configured on the charger matches the CSMS expectations
- Review certificate provisioning and rotation processes
[4, "msg-005", "SecurityError",
"Client certificate CN does not match charge point identity",
{"expected": "CP001", "received": "CP002"}]FormationViolation
Description: The payload is syntactically incorrect -- it is not valid JSON, or the JSON structure does not match the expected message format.
Common Causes:
- Malformed JSON (missing brackets, trailing commas, unescaped characters)
- Sending a string where the protocol expects a JSON array
- Incorrect encoding (the payload must be UTF-8)
- Truncated messages due to WebSocket framing issues
- Buffer overflow causing partial message transmission
How to Fix:
- Validate JSON syntax before sending any OCPP message
- Ensure your WebSocket library correctly handles message framing and does not split messages
- Use a JSON linter in your CI/CD pipeline to catch formation errors in test payloads
- Check character encoding settings on both sides
[4, "msg-006", "FormationViolation",
"Payload is not valid JSON",
{"receivedPayload": "{malformed..."}]PropertyConstraintViolation
Description: A property value in the payload violates a defined constraint (e.g., string length, numeric range, enum value).
Common Causes:
idTagexceeding the 20-character maximum length in OCPP 1.6- Negative value for
meterValueortransactionId - Enum value not in the allowed set (e.g., sending "Active" instead of "Charging" for ChargePointStatus)
- Timestamp not in ISO 8601 format
- String value exceeding
maxLengthdefined in the OCPP JSON schema
How to Fix:
- Validate all property values against the OCPP JSON schema constraints before sending
- Pay particular attention to string length limits, which vary by field
- Use the exact enum values specified in the OCPP specification (case-sensitive)
- Ensure numeric values fall within the defined ranges
[4, "msg-007", "PropertyConstraintViolation",
"idTag exceeds maximum length of 20 characters",
{"property": "idTag", "maxLength": 20, "actualLength": 25}]OccurrenceConstraintViolation
Description: A required property is missing from the payload, or a property that should appear only once appears multiple times.
Common Causes:
- Omitting required fields like
chargePointVendorinBootNotification - Missing
connectorIdinStatusNotification - Omitting
idTaginStartTransaction - Required nested objects not included (e.g., missing
chargingSchedulein aChargingProfile)
How to Fix:
- Cross-reference your message payloads against the OCPP specification for required vs optional fields
- Implement schema validation that checks required field presence before sending
- Be aware that required fields differ between OCPP 1.6 and 2.0.1 for the same action
- Check for conditional requirements (fields that are required only when another field has a specific value)
[4, "msg-008", "OccurrenceConstraintViolation",
"Required property 'chargePointVendor' is missing",
{"action": "BootNotification", "missingProperty": "chargePointVendor"}]TypeConstraintViolation
Description: A property has the wrong data type (e.g., a string where an integer is expected).
Common Causes:
- Sending
connectorIdas a string"1"instead of integer1 - Sending
meterValueas a string instead of a number - Boolean values sent as strings (
"true"instead oftrue) - Sending an integer where the schema expects a decimal number
- Date/time values not formatted as strings
How to Fix:
- Ensure JSON serialization preserves correct types (a common issue in dynamically typed languages)
- Validate payloads against the JSON schema with strict type checking
- Be especially careful with languages that auto-convert between strings and numbers
- Test with a schema validator that catches type mismatches
[4, "msg-009", "TypeConstraintViolation",
"Property 'connectorId' must be integer, received string",
{"property": "connectorId", "expectedType": "integer", "receivedType": "string"}]GenericError
Description: A catch-all error code for any error that does not fit the other categories.
Common Causes:
- Timeout waiting for a downstream system response
- Rate limiting or throttling
- Temporary resource contention
- Implementation-specific errors that have no matching standard code
- Edge cases not covered by the OCPP specification
How to Fix:
- Read the
errorDescriptioncarefully -- it is the primary source of information for GenericError - Check the
errorDetailsobject for implementation-specific context - Contact the CSMS or charger vendor if the error description is unclear
- Implement retry logic, as GenericError often indicates transient conditions
[4, "msg-010", "GenericError",
"Request timed out waiting for authorization service",
{"timeoutMs": 5000}]Error Code Summary Table
| Error Code | Severity | Retryable | Typical Source |
|---|---|---|---|
| NotImplemented | High | No | Version mismatch, wrong action name |
| NotSupported | Medium | No | Optional feature not available |
| InternalError | High | Yes | Server-side failure |
| ProtocolError | High | No | Message format violation |
| SecurityError | High | No | Authentication/authorization failure |
| FormationViolation | High | No | Invalid JSON syntax |
| PropertyConstraintViolation | Medium | No | Invalid field value |
| OccurrenceConstraintViolation | Medium | No | Missing required field |
| TypeConstraintViolation | Medium | No | Wrong data type |
| GenericError | Varies | Maybe | Catch-all for unclassified errors |
Common OCPP Troubleshooting Scenarios
Charger Will Not Connect
Symptoms: WebSocket connection fails or immediately closes after handshake.
Diagnostic Steps:
- Verify the CSMS WebSocket URL is correct, including the charge point identity in the path
- Check that the OCPP subprotocol header is present and matches a version the CSMS supports
- Confirm TLS certificates are valid if using WSS (check expiration, chain, and CN)
- Ensure the CSMS is configured to accept the charge point's identity
- Check firewall rules and load balancer configuration for WebSocket support
- Verify that no other charge point is connected with the same identity
Authorization Fails
Symptoms: Authorize requests return Invalid or Blocked status, or trigger CALLERROR.
Diagnostic Steps:
- Verify the
idTagis registered in the CSMS and is inAcceptedstatus - Check
idTagformat and length (max 20 characters in OCPP 1.6) - Confirm the authorization cache (Local Auth List) is synchronized between charger and CSMS
- Check if the parent
idTaggroup is blocked or expired - Verify the authorization service is responsive (InternalError in the response indicates a backend failure)
Transactions Stuck in Started State
Symptoms: Transactions never receive a StopTransaction and remain open indefinitely.
Diagnostic Steps:
- Check if the charger disconnected during a transaction (WebSocket connection dropped)
- Verify the charger is sending
StopTransactionwhen the cable is unplugged or session times out - Look for
InternalErrorresponses toStopTransactionthat may prevent the CSMS from processing the stop - Check for
transactionIdmismatches betweenStartTransactionresponse and subsequentStopTransaction - Implement transaction timeout logic on the CSMS side as a safety net
Meter Values Missing or Incorrect
Symptoms: Charging sessions show zero energy, or meter values have gaps or unrealistic values.
Diagnostic Steps:
- Verify
MeterValuesclock-aligned interval is configured on the charger - Check that the CSMS is correctly parsing the
sampledValuearray and its nested structure - Confirm
measurandvalues match what you expect (Energy.Active.Import.Register for cumulative energy) - Check for timezone issues -- meter value timestamps should be in UTC
- Verify that
MeterValuesmessages are not being dropped due to WebSocket disconnections
Debugging Tips
WebSocket Inspection
Use browser developer tools, wscat, or dedicated WebSocket clients to monitor raw OCPP messages. Capture the full message exchange including WebSocket handshake headers, subprotocol negotiation, and all CALL/CALLRESULT/CALLERROR frames.
Message Logging
Implement structured logging for every OCPP message with:
- Timestamp (millisecond precision)
- Direction (charger-to-CSMS or CSMS-to-charger)
- Message type (CALL, CALLRESULT, CALLERROR)
- Message ID
- Action name
- Full payload (redact sensitive fields like passwords)
- Processing duration
Timeout Analysis
OCPP does not define a standard timeout for CALL responses, but most implementations use 30-60 seconds. Track response times for every message type to identify:
- Slow actions that may indicate backend performance issues
- Timeouts that cause the sender to assume failure and retry
- Cascading timeouts from downstream service dependencies
How OCPPLab Helps Debug OCPP Errors
Reproducing OCPP errors with physical chargers is slow and limited. You cannot easily force a charger to send malformed JSON, trigger specific error codes, or reproduce timing-sensitive race conditions.
OCPPLab provides complete control over OCPP message flows for systematic error debugging:
- Full Message Inspection: View every OCPP message with timestamps, raw JSON payloads, and decoded field values. Identify exactly where in a message exchange an error occurs.
- Error Injection: Send specific CALLERROR responses to test how your CSMS handles each error code. Verify retry logic, fallback behavior, and error reporting.
- Malformed Message Testing: Send messages with missing fields, wrong types, invalid JSON, or constraint violations to validate your CSMS error handling covers all edge cases.
- Scenario Replay: Capture a problematic message sequence from production logs and replay it through OCPPLab to reproduce and diagnose the issue in a controlled environment.
- Concurrent Error Simulation: Test how your CSMS behaves when multiple chargers simultaneously encounter errors, revealing race conditions and resource exhaustion issues.
Frequently Asked Questions
Are OCPP error codes the same in 1.6 and 2.0.1?
The error codes themselves are identical between OCPP 1.6 and 2.0.1. Both versions use the same CALLERROR format and the same set of error code strings. However, 2.0.1 has additional actions and different payload schemas, so the specific constraint violations you encounter will differ.
Should my CSMS retry after receiving a CALLERROR?
It depends on the error code. InternalError and GenericError are often transient and worth retrying with exponential backoff. NotImplemented, NotSupported, FormationViolation, and constraint violations indicate permanent problems that retrying will not resolve. Always check the errorDescription for hints about whether the condition is temporary.
How do I handle errors in production?
Implement a layered approach: log every CALLERROR with full context, alert on elevated error rates, and build dashboards that track error codes by charger model and firmware version. Many production issues are firmware-specific, so correlating errors with charger metadata helps identify the root cause quickly.
What happens if neither side sends a response?
If a CALL receives no CALLRESULT or CALLERROR within the timeout period, the sender should consider the request failed. The OCPP specification does not define a specific timeout value, but implementations typically use 30 seconds. After a timeout, the sender may retry the request or close the connection and reconnect.
Can I define custom error codes?
No. The OCPP specification defines a fixed set of error codes, and both parties must use only these. If you need to communicate additional error context, use the errorDescription string and the errorDetails JSON object, which can contain any structured data you need.


