ChargeLink

Troubleshooting: Symptom to Action

Troubleshoot in layers. Do not jump to protocol decoding when the installed binary, license, NIC, port or gRPC service has not been proven. Every JSON failure carries a stable error code (CL-USAGE-001, CL-CONFIG-001, CL-LICENSE-001, CL-PROFILE-001, CL-RUNTIME-001, CL-ARTIFACT-001, CL-CONTRACT-001, CL-UNSUPPORTED-001, CL-IO-001, CL-SERIALIZATION-001, CL-INTERNAL-001) and an operator_action; read them first (exit codes).

The layers of an ISO 15118 session and where each one is diagnosed Order in which a session is established, and in which failures must be isolated 1 · SDP UDP 15118, multicastto ff02::1 on thelink-local interface Fails on: wrong NIC,IPv6 off, zone index,firewall Evidence:sdp_diagnostics.json 2 · TCP Advertised addressand port: 50118 or49152–65535 Fails on: wrongadvertise-ipv6, portrule, peer routing Evidence:evse_listener_status 3 · TLS ISO 15118-20:TLS 1.3 mutualISO 15118-2: optionalDIN 70121: none Fails on: version,chain, clock, missingclient certificate Evidence:tls_handshake_diagnostics.json 4 · V2GTP Frame header andpayload type0x8001 … 0x8004 Fails on: invalidlength or payloadtype, truncation Evidence: traces\live-v2gtp-frames 5 · EXI SupportedApp-Protocol, then theselected schema Fails on: decodeerror, unmatchedrequest encoding Evidence: decodeverdict per frame 6 · Session Setup, authorize,schedule, precharge,charge loop, stop Fails on: sequence,response budget,plant safety state Evidence: session_handshake_gate evse live-closure-gate --require-sdp --require-tcp-peer --require-tls --require-v2gtp --require-exi reports which layers were observed for a run.
Isolate failures layer by layer; each layer has its own evidence file.

Fast triage order

  1. Identity — version, license, profile.
  2. Environment — doctor, roots, permissions, NIC.
  3. Runtime — stale sessions, role locks, port ownership, gRPC health.
  4. Transport — IPv6 zone, SDP, TCP, TLS.
  5. Protocol — V2GTP, EXI, message sequence, response budgets.
  6. Integration — VeriStand mapping, automation client.
  7. Evidence — run ID, trace, first error timestamp.

Failure matrix

SymptomUsually meansCheck firstCorrective action
chargelink not foundPATH or installation pathTest-Path $CLUse the full path or the Start menu shell; only the default version is on PATH; reopen the shell after an installation.
Exit 2, CL-USAGE-001Wrong subcommand or flag for the installed versionchargelink <cmd> --helpCompare with the CLI reference; scripts from other releases must be checked.
Exit 70, CL-UNSUPPORTED-001The command is accepted by the parser but has no implementation in the installed version—Use the commands documented in this manual (for example test instead of scenario/suite/campaign).
Exit 20, CL-LICENSE-001No usable licence on this PC (none installed, expired, issued for another machine ID, maintenance ended, clock set back)license status; the message names the command and the reasonInstall the .dlic file with license install, or act on the state shown (Licensing).
Exit 10, CL-CONFIG-001Invalid configuration (for example --backend ethernet, empty PFX password variable, non-positive live-case value)the message fieldCorrect the option; the message names the accepted values.
Exit 40, CL-RUNTIME-001, "role lock"Another EVSE/EVCC session is live or stale in this runtime rootruntime list, runtime locksevse stop / evcc stop, or runtime recover --stale-only.
Different roots see different sessionsMissing --runtime-root/--artifact-root; defaults are relative to the working directorythe runtime_root field in any resultPass the same two root options on every command.
EVSE cannot bind / address in useAnother process owns UDP 15118 or the TCP portnetstat -ano | findstr ':15118 :50118'Stop the owner or use --tcp-port 0.
EVCC never discovers the EVSEWrong NIC, IPv6 disabled, zone index, firewallGet-NetAdapter, IPv6 binding, --interface-index, rules for UDP 15118 from fe80::/10Correct the adapter and advertised address; recreate the firewall rules.
"unreachable network" (10051) on the EVCCPeer address carries the peer's zone index instead of this machine's--peer-ipv6 suffixUse fe80::<peer>%<LOCAL_INDEX>.
SDP succeeds, TCP failsAdvertised address or port not reachablesdp_diagnostics.json, evse_listener_status.jsonAdvertise the bench adapter's link-local address; open the TCP port from fe80::/10.
TCP succeeds, TLS failsVersion, chain, clock or missing client certificatetls_handshake_diagnostics.json, evse tls-pki-doctor, w32tm /query /statusSee TLS and PKI. ISO 15118-20 needs TLS 1.3 mutual; do not use the SChannel or dev adapters.
TLS succeeds, then no protocol progressA DUT request that the reference responder does not answer, or a response time limit exceededtraces\live-v2gtp-frames.jsonl, session_handshake_artifact_gate.jsonIdentify the first unmatched or rejected frame; escalate with the trace. For ISO 15118-20 dynamic behaviour use the plant-coupled session on the NI VeriStand bench.
gRPC health failsServer not running, wrong endpoint, port conflictTest-NetConnection 127.0.0.1 -Port 50051Start integration serve; check the state root.
gRPC healthy, automation failsClient request or API version mismatchintegration session-smoke, capabilities.api_versionProve the built-in smokes, then debug the client against the proto of the same version.
GetProtocolState is unobservedBy design: the session carries no "listener" object, or the listener was started from the CLIbound-live-protocol-observer capabilityBind the session or read the listener artifacts; this is not a fault.
Every gRPC or REST call fails with CL-RUNTIME-001 "does not have valid authentication credentials"The client has no token or an old one (the server writes a new api-token at every start)the message names the file it triedSet CHARGELINK_API_TOKEN_FILE to the running server's <state-root>\api-token, or start the server with the runtime root's default state root.
integration serve exits 40 at start--listen names a non-loopback addressthe diagnostic envelopeUse 127.0.0.1 or [::1]; remote access is not offered.
VeriStand bench: the ChargeLink Operator screen does not open, or the charger's listener does not get ready (last error 3201)Another VeriStand project deployed or another program holding the VeriStand gateway, VeriStand not licensed, no ChargeLink licence, a port in use, ChargeLink programs left from an earlier sessionlauncher.log and the operator log in operator\ of the run folder runs\<time>-veristand; Operator.LastErrorCodeClose the other VeriStand client; end leftover chargelink.exe and other ChargeLink programs; check chargelink license status; see NI VeriStand Bench, Troubleshooting.
VeriStand bench: plant values do not moveSafe start-up state held, session not started, safety input active, or a plant fault latched (a display-only channel written by hand)the ChargeLink Operator screen: Session, External EVCC, Operator.LastErrorCode, Safety.FaultActivePress Apply safe startup, Start session and Start external EVCC in this order; press Reset plant to recover from a plant fault; run the import again if the configuration was changed; see VeriStand Signal Mapping.
Rate stabilisation timeoutEngine rate too high for the PCengine rate, power plan, CPU loadUse the 500 Hz SIL configuration; repeat the timing check.
Scripted DC-CAN "hardware" run has hardware_loop_evidence_complete: falseExpected: the scripted sequences start no CAN driver; hardware mode records an operator attestation—None; see Scripted DC-CAN Sequences.
Test case shows inconclusive or blockedNo evidence bound, or prerequisite absentcampaign_status.jsonAttach an evidence manifest (test run --evidence live); satisfy or document the blocker. Never relabel as FAIL.
No artifactsWrong artifact root or permissionglobal --artifact-root, directory ACLUse an explicit writable root; preserve any failure evidence before retrying.
Integrity check failsFiles changed after the runartifacts integrity outputQuarantine and repeat the run; do not regenerate the manifest.

Layer checks

Identity and environment

chargelink --version
chargelink --json license status
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json env doctor --strict
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json profile show <PROFILE_ID>

Runtime

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime list
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime locks
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime inspect --run-id <RUN_ID>
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime recover --stale-only --dry-run
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime recover --stale-only

Transport

Get-NetAdapter | Format-Table ifIndex,Name,Status -AutoSize
Get-NetIPAddress -AddressFamily IPv6 | Where-Object IPAddress -like 'fe80::*' | Format-Table InterfaceIndex,InterfaceAlias,IPAddress -AutoSize
ping -6 'fe80::<PEER>%<LOCAL_INDEX>'
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse live-preflight --source external-evcc --protocol <P> --profile-id <ID> --host '::' --tcp-port 50118 --udp-port 15118 --advertise-ipv6 $Advertise --interface-index $IfIndex

Protocol

Get-Content "$Data\artifacts\<RUN_ID>\traces\live-v2gtp-frames.jsonl" | Select-Object -First 40
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse live-closure-gate --run-id <RUN_ID> --source external-evcc --require-sdp --require-tcp-peer --require-v2gtp --require-exi

Useful separation: SDP → TCP → TLS → V2GTP → EXI/application → charging sequence. A later-layer failure does not invalidate earlier transport success; say which layer failed when escalating.

Prepare a support bundle

Preserve the failing run directory, then follow Support Escalation. Do not rerun over the same run ID.