---
title: Troubleshooting
description: Common errors and how to fix them
sidebar:
  order: 4
---

Organized by the error message you see. Each entry covers the cause and the fix.

## Connection errors

### "Not connected to OpenOCD. Use connect or start_openocd first."

**Cause**: No active OpenOCD session. This appears when you call any tool (except
`connect`, `start_openocd`, or `disconnect`) before establishing a connection.

**Fix**: Either connect to a running OpenOCD instance:
```
connect("localhost", 6666)
```

Or spawn one with a config file:
```
start_openocd("/path/to/your/config.cfg")
```

Or set `OPENOCD_CONFIG` in your environment so mcjtag auto-connects on startup.

### "Connection failed" / "Cannot connect to OpenOCD"

**Cause**: OpenOCD is not running, or it is running on a different host/port.

**Fix**:

1. Verify OpenOCD is running:
   ```bash
   ps aux | grep openocd
   ```
2. Check which port it is listening on. The default TCL port is 6666. Look for
   `-c "tcl_port XXXX"` in the OpenOCD command line if a non-default port was used.
3. If connecting to a remote host, confirm the `OPENOCD_HOST` and `OPENOCD_PORT`
   environment variables are correct.
4. Try connecting manually with netcat to test basic connectivity:
   ```bash
   echo "version" | nc localhost 6666
   ```

### "Already connected. Disconnect first to reconnect."

**Cause**: You called `connect()` or `start_openocd()` while a session is already active.

**Fix**: Call `disconnect()` first, then connect again.

## Target errors

### "Error: Target not halted"

**Cause**: Trying to read registers, access certain memory regions, or perform
operations that require the CPU to be stopped.

**Fix**:
```
target_control("halt")
```

Some operations (like `read_memory` on flash) work while the target is running
on some chips, but register reads always require a halted target.

### "No JTAG TAPs found"

**Cause**: The JTAG chain scan found no devices.

**Fix** (check in order):

1. **Ground**: Confirm GND is connected between the probe and target. This is the
   most common cause.
2. **Power**: Verify the target board has power. Check its power LED.
3. **Wiring**: Double-check SWDIO/SWCLK (SWD) or TDI/TDO/TMS/TCK (JTAG) connections.
   See [Hardware Setup](/guides/hardware-setup/) for pinout details.
4. **Transport**: Make sure you selected the right transport in your config. If your
   wiring is SWD, the config must say `transport select swd` (not `jtag`).
5. **Speed**: Try reducing the adapter speed to 100 kHz in your OpenOCD config:
   ```tcl
   adapter speed 100
   ```
   Long wires and breadboards degrade signal integrity.
6. **Probe firmware**: Some probes need a firmware update. For DAP-Link, check the
   firmware version matches your expected capabilities.

## Memory errors

### "Write to 0x... is outside safe write ranges"

**Cause**: `write_memory()` was called with an address outside the configured safe
ranges. By default, only SRAM (0x20000000-0x20100000) is writable.

**Fix**: Either write to an address within SRAM, or expand the safe write ranges.
See [Safety Configuration](/guides/safety-configuration/) for details.

```bash
# Example: also allow peripheral writes
MCJTAG_SAFE_WRITE_RANGES="0x20000000-0x20100000,0x40000000-0x50000000"
```

### "Unaligned N-bit write at 0x..."

**Cause**: The write address is not aligned to the element width. A 32-bit write
requires a 4-byte-aligned address, 16-bit requires 2-byte aligned.

**Fix**: Align the address, or use 8-bit writes for unaligned locations:
```
write_memory("0x20000001", ["0xAB"], width=8)
```

### "count N exceeds maximum 4096"

**Cause**: `read_memory()` was called with `count` greater than 4096.

**Fix**: Split the read into multiple smaller calls. For example, to read 8192 words:
```
read_memory("0x20000000", count=4096)
read_memory("0x20004000", count=4096)
```

## Flash errors

### "Firmware image not found"

**Cause**: The file path passed to `flash_program()` does not exist.

**Fix**: Check the path. Use an absolute path to avoid working directory ambiguity.

### "Unsupported file type '.xxx'"

**Cause**: The firmware file has an extension not in the allowed list.

**Fix**: Use one of the supported formats: `.bin`, `.hex`, `.elf`, `.ihex`, `.srec`, `.s19`.
If your build system produces a different extension, rename or convert the file.

### "Flash error: ..."

**Cause**: OpenOCD failed during the erase, write, or verify phase. Common reasons:

- Target not halted (halt it first with `target_control("halt")`)
- Flash is read-protected (some chips have RDP/security bits)
- Wrong target config (the flash driver does not match the chip)
- Corrupted firmware file

**Fix**: Halt the target, verify the target config matches your chip, and try again.
If the chip has read protection enabled, you may need to mass-erase it first using
a vendor-specific tool.

## Raw command errors

### "Blocked: '...' matches destructive pattern '...'"

**Cause**: `raw_command()` caught a command that matches the deny-list.

**Fix**: Use the dedicated tool instead:

| Blocked command | Dedicated tool |
|---|---|
| `flash write_image` | `flash_program()` |
| `mww`, `mwh`, `mwb` | `write_memory()` |
| `reset` | `target_control("reset_halt")` or `target_control("reset_run")` |
| `shutdown` | `disconnect()` |
| `reg` | `write_register()` |

If you need unrestricted access, set `MCJTAG_ALLOW_RAW=true`.

## SVD errors

### "No SVD file loaded" / "svd_loaded: false"

**Cause**: `svd_inspect()` was called without loading an SVD file first.

**Fix**: Load one explicitly:
```
svd_inspect(svd_path="/path/to/STM32F103xx.svd")
```

Or set `OPENOCD_SVD` in your environment for auto-loading on startup.
See [SVD Register Decoding](/guides/svd-register-decoding/) for details on finding
SVD files for your chip.

### "SVD file not found" / "Expected .svd file"

**Cause**: The path is wrong, or the file does not have a `.svd` extension.

**Fix**: Verify the path and extension. SVD files must end in `.svd` (case-insensitive).

## Probe-specific issues

### DAP-Link not detected

1. Check USB connection — try a different cable or port
2. Verify the device appears on the bus:
   ```bash
   # Linux
   lsusb | grep -i dap

   # macOS
   system_profiler SPUSBDataType | grep -i dap
   ```
3. Check kernel messages for errors:
   ```bash
   dmesg | tail -20
   ```
4. On Linux, you may need a udev rule for non-root access:
   ```bash
   echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="0d28", MODE="0666"' | sudo tee /etc/udev/rules.d/50-daplink.rules
   sudo udevadm control --reload-rules
   sudo udevadm trigger
   ```

### ST-Link "Error: open failed" or "LIBUSB_ERROR"

1. Verify ST-Link firmware is up to date (use ST's firmware update tool)
2. On Linux, install the ST-Link udev rules:
   ```bash
   # Usually shipped with stlink-tools package
   sudo apt install stlink-tools
   ```
3. If using a Nucleo board, make sure the ST-Link jumpers are in the correct
   position for on-board debugging (not external target mode)

### OpenOCD exits immediately

**Cause**: Configuration error — wrong interface, target, or permissions.

**Fix**: Run OpenOCD manually to see the full error output:
```bash
openocd -f /path/to/your/config.cfg
```

Common issues:
- Config file path is wrong — OpenOCD prints "Can't find ..." and exits
- Wrong target config for your chip — OpenOCD prints "Error: target didn't examine"
- Permission denied on USB device — see the udev rules section above
- Another OpenOCD instance is already running on the same port — kill it first
