# Error Handling

> **Library 2.0.0.213** · SAE J2534 v04.04 API

Every function returns `int32_t`: `STATUS_NOERROR` (0) or an error code.

## The ERR_FAILED pattern

`ERR_FAILED` (0x07) is the generic failure code. Whenever you receive it, call
`PassThruGetLastError` for a human-readable reason:

```c
int32_t ret = PassThruWriteMsgs(channel_id, &msg, &num, 1000);
if (ret == J2534_ERR_FAILED) {
    char err[256] = {0};
    PassThruGetLastError(err);
    // e.g. "0x6E - Connection timed out"  (POSIX)
    // e.g. "0x274C - A connection attempt failed ..." (Windows/WinSock)
    log("J2534 error: %s", err);
}
```

Message conventions:

- **System-level failures** (socket, BLE, serial): `"0x<code> - <description>"`,
  where the code is the platform error (`errno` on POSIX, `WSAGetLastError()`
  on Windows).
- **Library-level failures**: a plain descriptive message, e.g.
  `"j2534.json parse error"`.

`PassThruGetLastError` reports the error of the most recent failed call in the
current process; query it immediately after the failure.

## Return codes

| Code | Name | Meaning |
|------|------|---------|
| 0x00 | `STATUS_NOERROR` | Success |
| 0x01 | `ERR_NOT_SUPPORTED` | Function/feature not supported |
| 0x02 | `ERR_INVALID_CHANNEL_ID` | Unknown channel handle |
| 0x03 | `ERR_PROTOCOL_ID_NOT_SUPPORTED` | Protocol not supported |
| 0x04 | `ERR_NULL_PARAMETER` | NULL where a pointer is required |
| 0x05 | `ERR_INVALID_IOCTL_VALUE` | Bad IOCTL value |
| 0x06 | `ERR_FLAG_NOT_SUPPORTED` | Unsupported flag bit |
| 0x07 | `ERR_FAILED` | Generic failure — call `PassThruGetLastError` |
| 0x08 | `ERR_DEVICE_NOT_CONNECTED` | Transport to the device is down (socket closed, BLE not ready, serial port not open) |
| 0x09 | `ERR_TIMEOUT` | Operation timed out |
| 0x0A | `ERR_INVALID_MSG` | Malformed message for the protocol |
| 0x0B | `ERR_TIME_INTERVAL_NOT_SUPPORTED` | Bad periodic interval |
| 0x0C | `ERR_EXCEEDED_LIMIT` | Out of filters/periodic slots/devices |
| 0x0D | `ERR_INVALID_MSG_ID` | Unknown periodic/filter handle |
| 0x0E | `ERR_DEVICE_IN_USE` | Device already open by another process |
| 0x0F | `ERR_IOCTL_ID_NOT_SUPPORTED` | Unknown IOCTL for this channel |
| 0x10 | `ERR_BUFFER_EMPTY` | No messages available (not a fault) |
| 0x11 | `ERR_BUFFER_FULL` | TX queue full |
| 0x12 | `ERR_BUFFER_OVERFLOW` | RX queue overflowed; messages lost |
| 0x13 | `ERR_PIN_NOT_SUPPORTED` | Invalid J1962 pin |
| 0x14 | `ERR_CHANNEL_IN_USE` / `ERR_RESOURCE_CONFLICT` | Resource (pin/controller) already in use |
| 0x15 | `ERR_MSG_PROTOCOL_ID` | Message protocol ≠ channel protocol |
| 0x16 | `ERR_INVALID_FILTER_ID` | Unknown filter handle |
| 0x17 | `ERR_NO_FLOW_CONTROL` | ISO 15765 send without a flow-control filter |
| 0x18 | `ERR_NOT_UNIQUE` | Duplicate filter/periodic message |
| 0x19 | `ERR_BAUDRATE_NOT_SUPPORTED` | Unachievable baud rate |
| 0x1A | `ERR_INVALID_DEVICE_ID` | Unknown device handle |
| 0x1B | `ERR_DEVICE_NOT_OPEN` | Call on a device that was never opened |
| 0x1C | `ERR_NULL_REQUIRED` | Parameter must be NULL |
| 0x1D | `ERR_FILTER_TYPE_NOT_SUPPORTED` | Bad filter type for this channel |
| 0x1E | `ERR_IOCTL_PARAM_ID_NOT_SUPPORTED` | Unknown SET_CONFIG/GET_CONFIG parameter |
| 0x1F | `ERR_VOLTAGE_IN_USE` | Programming voltage already applied |
| 0x20 | `ERR_PIN_IN_USE` | Pin already in use |
| 0x21 | `ERR_INIT_FAILED` | Five-baud / fast init failed |
| 0x22 | `ERR_OPEN_FAILED` | Device open failed (bad connection string, unreachable device) |
| 0x23 | `ERR_BUFFER_TOO_SMALL` | Output buffer too small |
| 0x24 | `ERR_LOG_CHAN_NOT_ALLOWED` | Logical channel not allowed here |
| 0x25 | `ERR_SELECT_TYPE_NOT_SUPPORTED` | Bad select type |

## Practical notes

- **`ERR_BUFFER_EMPTY` and `ERR_TIMEOUT` on `PassThruReadMsgs` are normal
  flow control**, not failures: keep polling or extend the timeout.
- **`ERR_DEVICE_NOT_CONNECTED`** means the transport dropped. Close the device
  (`PassThruClose`) and re-open; for USB the device may need ~300 ms to
  re-enumerate after a reset.
- **`ERR_DEVICE_IN_USE`** — the adapter accepts one host at a time. Make sure
  no other application (including Quantex software) holds the device.
- **`ERR_NO_FLOW_CONTROL`** — set a `FLOW_CONTROL_FILTER` before writing on an
  ISO 15765 channel.
- After `PassThruConnect` on `ISO13400_PS`/`HSFZ_PS` channels, network
  bring-up can take up to ~15 s on a slow Ethernet link — use generous
  timeouts for the first IOCTLs (see [DOIP.md](DOIP.md)).
- For deep debugging, read the library log (`.qlog`) — every API call, its
  parameters, result and timing are recorded. See
  [LOG_FORMAT.md](LOG_FORMAT.md) and
  [CONFIGURATION.md](CONFIGURATION.md#logging) for the location.
