Troubleshooting
Playing, not building? See Problems in the user guide.
Each entry starts with what you see. Run the fix, then repeat the step that failed.
A block without tabs is written for Linux and macOS. On Windows, write python for python3, .venv\Scripts for .venv/bin and $HOME for ~, and in PowerShell put quotes around -D arguments: "-DSDKCONFIG=…".
Jump to: Install · Build · Flash · Checks and tests · Simulator · Apps · MCP
Faster: press Ctrl+K (⌘+K on macOS) to open the search and paste the first line of the error. Every entry quotes the message it covers.
Install
Section titled “Install”apt-get install fails or a package is not found
Section titled “apt-get install fails or a package is not found”Cause: The package lists are stale or there is no network, or your distro does not use apt-get.
Fix:
sudo apt-get updateThen run the install step again. On Fedora, use sudo dnf install -y with the package names from 1. Set up the toolchain; on Arch or openSUSE, use pacman or zypper.
xcode-select or brew is missing or fails (macOS)
Section titled “xcode-select or brew is missing or fails (macOS)”Cause: The Apple command line tools or Homebrew are not installed yet, or Homebrew’s package lists are stale.
Fix:
xcode-select -p || xcode-select --installbrew updateIf xcode-select -p prints no folder, a window asks to install the tools: click Install and wait. If brew is not found, install Homebrew with the command on brew.sh. Then run the install step again.
python3 is missing or too old
Section titled “python3 is missing or too old”Cause: python3 is not installed or is older than 3.10 (the installer stops with Python … is too old).
Fix:
sudo apt-get updatesudo apt-get install -y python3 python3-venv python3-pippython3 --versionbrew install python3python3 --versionThe version must be 3.10 or newer. If your distro has no newer python3, install one from your distro’s backports or from python.org.
Running scripts is disabled on this system
Section titled “Running scripts is disabled on this system”Cause: PowerShell’s execution policy is Restricted, so it refuses to load export.ps1.
Fix: The first line works for this window only; the last one lasts for your user.
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force# or permanently, for your user:Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSignedIf both are refused, a group policy blocks scripts and only an administrator can change it.
Git or Python not found after install
Section titled “Git or Python not found after install”Cause: The PowerShell window still has the old PATH (The term 'git' is not recognized), or python is the Microsoft Store alias.
Fix:
$env:Path = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")git --versionpython --versionOr open a new PowerShell window. If python opens the Microsoft Store, turn off its entries in Settings → Apps → Advanced app settings → App execution aliases.
CrossPad ESP-IDF folder shows the side-by-side folder
Section titled “CrossPad ESP-IDF folder shows the side-by-side folder”Cause: A failed earlier clone, or an ESP-IDF that is not a git checkout, sits in ~/esp/esp-idf (C:\CrossPad\esp-idf), so the check sends CrossPad’s copy to ~/esp/esp-idf-v5.5 (C:\CrossPad\esp-idf-v5.5).
Fix: Move the broken folder away, then set the variable again.
mv ~/esp/esp-idf ~/esp/esp-idf.oldCROSSPAD_IDF_DIR=~/esp/esp-idfecho "export CROSSPAD_IDF_DIR=$CROSSPAD_IDF_DIR" >> ~/.bashrc # macOS: ~/.zshrcRename-Item C:\CrossPad\esp-idf esp-idf.old$env:CROSSPAD_IDF_DIR = "C:\CrossPad\esp-idf"[Environment]::SetEnvironmentVariable("CROSSPAD_IDF_DIR", $env:CROSSPAD_IDF_DIR, "User")Then run the download step again. Only move the folder if it is broken; a working ESP-IDF of another version should stay. Remove duplicate export CROSSPAD_IDF_DIR= lines from ~/.bashrc or ~/.zshrc so only one is left.
Other ESP-IDF mix-ups: wrong version active, CP Tools uses the wrong one, installer picked a different one, Python environment of another ESP-IDF.
ESP-IDF download fails
Section titled “ESP-IDF download fails”Cause: A folder from an earlier attempt is in the way (fatal: destination path … already exists), or the network dropped.
Fix: First check whether the folder already holds a working clone.
echo $CROSSPAD_IDF_DIRgit -C "$CROSSPAD_IDF_DIR" describe --tags$env:CROSSPAD_IDF_DIRgit -C $env:CROSSPAD_IDF_DIR describe --tagsIf the first line prints nothing, set the variable first as in 1. Set up the toolchain. Then read what describe printed:
v5.5.5: the clone worked. Skip to the tools step.- Another version tag: the folder is a complete ESP-IDF, maybe one your other projects use. Do not delete or move it. Set
CROSSPAD_IDF_DIRto a new, empty folder for CrossPad (the same lines as in the folder step of 1. Set up the toolchain, with your folder), and run the download step again. - A line starting with
fatal:that names a folder which does not exist: the network dropped before anything was written. Run the download step again. - Any other line starting with
fatal:, and the folder did not exist before you started the CrossPad steps: it is a half-finished CrossPad download. Move it aside and run the download step again, as below. If the folder was there before, it may be an ESP-IDF installed without git that other projects use: keep it and setCROSSPAD_IDF_DIRto a new, empty folder as above.
mv "$CROSSPAD_IDF_DIR" "$CROSSPAD_IDF_DIR.broken"Move-Item $env:CROSSPAD_IDF_DIR "$env:CROSSPAD_IDF_DIR.broken"Delete the .broken folder once the tools step has worked.
If git says Filename too long, see git says Filename too long.
git says Filename too long (Windows)
Section titled “git says Filename too long (Windows)”Cause: Windows long paths are off for git, so a deep path in ESP-IDF or a submodule cannot be written.
Fix:
git config --global core.longpaths trueThen check the half-finished ESP-IDF folder and move it aside, or for the project update its submodules, and run the step again.
ESP-IDF tools install fails
Section titled “ESP-IDF tools install fails”Cause: A download was cut off, or the ESP-IDF Python environment is broken (on Linux, often because python3-venv was missing when it was made).
Fix: Delete the ESP-IDF Python environment and run the tools install again.
sudo apt-get install -y python3-venv gitrm -rf ~/.espressif/python_env/idf5.5_*IDF_TOOLS_PATH=~/.espressif "$CROSSPAD_IDF_DIR/install.sh" esp32s3rm -rf ~/.espressif/python_env/idf5.5_*IDF_TOOLS_PATH=~/.espressif "$CROSSPAD_IDF_DIR/install.sh" esp32s3Remove-Item -Recurse -Force C:\CrossPad\.espressif\python_env\idf5.5_*$env:IDF_TOOLS_PATH = "C:\CrossPad\.espressif"& "$env:CROSSPAD_IDF_DIR\install.bat" esp32s3Wait for All done!. Keep ESP-IDF, its tools and the project in folders without spaces or non-English letters.
Python environment is set to … which was generated for another ESP-IDF, or “called from a virtual environment”
Section titled “Python environment is set to … which was generated for another ESP-IDF, or “called from a virtual environment””Cause: Another ESP-IDF is loaded in this terminal (for example from your shell profile), and its IDF_PYTHON_ENV_PATH points the installer at that version’s Python environment.
Fix: Forget the other ESP-IDF in this terminal, then run the step again.
unset IDF_PATH IDF_PYTHON_ENV_PATHPATH=$(printf %s "$PATH" | tr : '\n' | grep -v -e /.espressif/ -e /esp-idf | paste -sd: -)Remove-Item Env:IDF_PATH, Env:IDF_PYTHON_ENV_PATH -ErrorAction SilentlyContinue$env:Path = ($env:Path -split ';' | Where-Object { $_ -notmatch '\\\.espressif\\|\\esp-idf' }) -join ';'The same applies to This script was called from a virtual environment, can not create a virtual environment again: the other version’s Python is still first on PATH.
Keep the other version’s export.sh line out of your shell profile if you work mostly on CrossPad; see Use several ESP-IDF versions.
Other ESP-IDF mix-ups: side-by-side folder, wrong version active, CP Tools uses the wrong one, installer picked a different one, Python environment of another ESP-IDF.
Wrong ESP-IDF version is active
Section titled “Wrong ESP-IDF version is active”Cause: idf.py --version prints a version older than 5.5.4 or outside 5.5.x because another ESP-IDF’s export script ran last (often from your shell profile), or CROSSPAD_IDF_DIR points at the wrong folder.
Fix:
echo $CROSSPAD_IDF_DIR. "$CROSSPAD_IDF_DIR/export.sh"idf.py --version$env:CROSSPAD_IDF_DIR$env:IDF_TOOLS_PATH = "C:\CrossPad\.espressif". "$env:CROSSPAD_IDF_DIR\export.ps1"idf.py --versionCrossPad needs 5.5.4 or a newer 5.5.x; ESP-IDF 6.x is not supported. If the variable is wrong, set it again as in 1. Set up the toolchain. If a profile line loads another ESP-IDF’s export.sh, delete that line.
Other ESP-IDF mix-ups: side-by-side folder, CP Tools still uses the old one, installer picked a different one, Python environment of another ESP-IDF.
export.ps1 says the Python virtual environment is not found (Windows)
Section titled “export.ps1 says the Python virtual environment is not found (Windows)”Cause: IDF_TOOLS_PATH was not set before export.ps1, so it looks for the tools in your user folder (ESP-IDF Python virtual environment … not found, or a tool has no installed versions).
Fix:
$env:IDF_TOOLS_PATH = "C:\CrossPad\.espressif". "$env:CROSSPAD_IDF_DIR\export.ps1"idf.py --versionSet IDF_TOOLS_PATH in every new PowerShell window before export.ps1.
Permission denied on the serial port
Section titled “Permission denied on the serial port”Cause: Your Linux user is not in the dialout group, or you have not logged out and in since you were added (Permission denied: '/dev/ttyACM…').
Fix:
sudo usermod -aG dialout $USERgroupsLog out and back in (or restart); then groups lists dialout. On Arch and some other distros the group is uucp.
Project clone fails
Section titled “Project clone fails”Cause: The network dropped or the clone was interrupted, so submodules are missing.
Fix:
git -C ~/CrossPad submodule update --init --recursivegit -C ~/CrossPad submodule status | grep -c '^-' || truegit -C C:\CrossPad\firmware submodule update --init --recursive(git -C C:\CrossPad\firmware submodule status | Select-String '^-').CountThe count must be 0. For the simulator, run the same submodule update in its folder. A clone cut short can also leave a submodule folder empty although the count is 0; the build then stops on a missing file under lib/. Fill it with git submodule foreach --recursive 'git checkout -f HEAD' in the project folder, or clone again. If git says Filename too long, see git says Filename too long.
CP Tools uses the wrong ESP-IDF
Section titled “CP Tools uses the wrong ESP-IDF”Cause: CP Tools builds with another ESP-IDF, or doctor says ESP-IDF not found, because crosspad.local.json was written from a terminal where CROSSPAD_IDF_DIR was empty or the tools folder was wrong, or an IDF_PATH variable overrides the file.
Fix: Check the variable, then write the file again.
echo $CROSSPAD_IDF_DIRprintf '{"idf_path": "%s", "idf_tools_path": "%s"}\n' "$CROSSPAD_IDF_DIR" ~/.espressif > ~/CrossPad/crosspad.local.jsoncat ~/CrossPad/crosspad.local.json$env:CROSSPAD_IDF_DIR@{ idf_path = $env:CROSSPAD_IDF_DIR; idf_tools_path = "C:\CrossPad\.espressif" } | ConvertTo-Json | Set-Content -Encoding ascii C:\CrossPad\firmware\crosspad.local.jsonGet-Content C:\CrossPad\firmware\crosspad.local.jsonIf the variable prints nothing, open a new terminal (or run . ~/.bashrc) first. CP Tools prefers IDF_PATH to the file, and every export.sh or export.ps1 sets it, so clear it in the terminal you run CP Tools from:
echo $IDF_PATHunset IDF_PATHgrep -n IDF_PATH ~/.bashrc ~/.zshrc 2>/dev/null$env:IDF_PATHRemove-Item Env:IDF_PATH -ErrorAction SilentlyContinue[Environment]::GetEnvironmentVariable("IDF_PATH", "User")If grep shows an export IDF_PATH= line, delete that line from the file. On Windows, if the last line prints a folder, remove the stored variable with [Environment]::SetEnvironmentVariable("IDF_PATH", $null, "User").
Other ESP-IDF mix-ups: side-by-side folder, wrong version active, installer picked a different one, Python environment of another ESP-IDF.
crosspad-hil install fails
Section titled “crosspad-hil install fails”Cause: The venv module is missing, or a dependency without a prebuilt wheel (python-rtmidi) needs a compiler and the ALSA headers.
Fix:
sudo apt-get install -y python3-venv build-essential libasound2-devpython3 -m venv ~/CrossPad/.venv~/CrossPad/.venv/bin/pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"~/CrossPad/.venv/bin/crosspad-hil --versionpython3 -m venv ~/CrossPad/.venv~/CrossPad/.venv/bin/pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"~/CrossPad/.venv/bin/crosspad-hil --versionpython -m venv C:\CrossPad\firmware\.venvC:\CrossPad\firmware\.venv\Scripts\pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"C:\CrossPad\firmware\.venv\Scripts\crosspad-hil --versionOn macOS the compiler comes with the Apple command line tools. Flashing still works without crosspad-hil: pass --board v2 to the flash script.
The one-line installer stops with an error
Section titled “The one-line installer stops with an error”Cause: One step failed (network, a package, a download) and the installer stopped at its red line.
Fix: Run the same line again; it redoes only what is missing and keeps your changes.
curl -fsSL https://raw.githubusercontent.com/CrossPad/crosspad-apps/main/install/install.sh | bashls /tmp/crosspad-*.logpowershell -ExecutionPolicy Bypass -c "irm https://raw.githubusercontent.com/CrossPad/crosspad-apps/main/install/install.ps1 | iex"dir $env:TEMP\crosspad-setup\*.logThe logs show the failing command. Still stuck: in ~/CrossPad run python3 tools/app_manager.py (Windows: in C:\CrossPad\firmware, python tools\app_manager.py), or cptools if the installer got far enough to create that command. Press 3 (Something’s wrong), press s to save a report, and post it in the CrossPad Discord, #support.
The installer picked a different ESP-IDF
Section titled “The installer picked a different ESP-IDF”Cause: With several ESP-IDFs installed, the installer takes the highest 5.5.x it finds, and every re-run detects again instead of reusing your earlier choice.
Fix: Pin your ESP-IDF on every run. Replace /path/to/your/esp-idf (Windows: C:\path\to\your\esp-idf) with its folder.
export CROSSPAD_IDF_DIR=/path/to/your/esp-idf IDF_TOOLS_PATH=~/.espressifcurl -fsSL https://raw.githubusercontent.com/CrossPad/crosspad-apps/main/install/install.sh | bash$env:CROSSPAD_IDF_DIR="C:\path\to\your\esp-idf"; powershell -ExecutionPolicy Bypass -c "irm https://raw.githubusercontent.com/CrossPad/crosspad-apps/main/install/install.ps1 | iex"The installer does not check the version of a pinned folder, so point it only at a 5.5.x checkout. Every variable the installer reads is listed in its README. More: Use several ESP-IDF versions.
Other ESP-IDF mix-ups: side-by-side folder, wrong version active, CP Tools uses the wrong one, Python environment of another ESP-IDF.
idf.py command not found
Section titled “idf.py command not found”Cause: ESP-IDF is not loaded in this terminal, or CROSSPAD_IDF_DIR is empty because the new terminal did not read your profile.
Fix:
echo $CROSSPAD_IDF_DIR. "$CROSSPAD_IDF_DIR/export.sh"idf.py --version$env:CROSSPAD_IDF_DIR$env:IDF_TOOLS_PATH = "C:\CrossPad\.espressif". "$env:CROSSPAD_IDF_DIR\export.ps1"idf.py --versionIf the variable is empty, check the export line in ~/.bashrc or ~/.zshrc, or the User environment variable on Windows. Installer users can run crosspad-idf instead of idf.py.
idf.py board shows no board revision
Section titled “idf.py board shows no board revision”Cause: No revision is remembered for this project and no board is connected to detect one (no board revision known, exit code 2).
Fix: In the project folder:
idf.py board --set v2idf.py boardUse v1 for a board with PCB r16 / r19.
idf.py build says No board revision chosen for this build
Section titled “idf.py build says No board revision chosen for this build”Cause: A bare idf.py build has no board revision, so CMake stops with a FATAL_ERROR that asks for -B and -DSDKCONFIG.
Fix: Name the build folder and sdkconfig of the board’s revision.
idf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 buildOn a v1 board use build_v1 and sdkconfig.v1.
Build stops before Project build complete
Section titled “Build stops before Project build complete”Cause: A component download from the ESP component registry was cut off, or the build folder is stale after apps changed or an earlier build failed.
Fix: Clean the build folder and build again.
idf.py --versionidf.py -B build_v2 fullcleanidf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 buildOn a v1 board use build_v1 and sdkconfig.v1. If the version is not 5.5.4 or a newer 5.5.x, see Wrong ESP-IDF version is active.
OTA flash cannot find the board
Section titled “OTA flash cannot find the board”Cause: The board is off or on a charge-only cable, or nobody pressed Allow on the “USB serial mode?” prompt within 10 seconds (Error: CrossPad not found (neither CDC nor MIDI)).
Fix: Run the script again and press Allow as soon as the board shows it.
python3 tools/ota_flash.pypython3 tools/ota_flash.py --port /dev/ttyACM0python tools\ota_flash.pypython tools\ota_flash.py --port COM5You can switch USB serial on in advance on the board under Settings → USB → Mode → MIDI + Serial. Use a data cable. On Linux, a missing serial port permission shows Permission denied instead: see serial port permissions.
OTA times out waiting for confirmation
Section titled “OTA times out waiting for confirmation”Cause: Nobody pressed Update on the board within 60 seconds, so the script stops with Error: expected OTA_READY, got: ….
Fix:
python3 tools/ota_flash.pypython tools\ota_flash.pyPress Update when it shows. Tick Auto-accept updates once to skip the prompt from then on.
Board rolls back to the old firmware
Section titled “Board rolls back to the old firmware”Cause: The board was reset or unplugged within 10 seconds of the restart, or the new image did not finish starting before it could confirm itself.
Fix: Flash again and leave the board alone for 10 seconds.
python3 tools/ota_flash.pypython tools\ota_flash.pyIf it rolls back again, watch the boot log for errors. If OTA keeps failing, flash over UART.
OTA flash says the revision of the board is unknown
Section titled “OTA flash says the revision of the board is unknown”Cause: crosspad-hil is missing from the project’s .venv or cannot see the board, so the script cannot check the image against it (Error: the revision of the board on … is unknown).
Fix:
python3 tools/ota_flash.py --board v2python tools\ota_flash.py --board v2Use --board v1 on a board with PCB r16 / r19. To let the script detect the board again, install crosspad-hil.
OTA says the image is not built
Section titled “OTA says the image is not built”Cause: There is no image for the board’s revision yet (Error: … is not built), often because you built the other revision.
Fix: Build the revision the error names, then flash again.
idf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 buildThe error line prints the exact build command.
OTA refuses an image for the other revision
Section titled “OTA refuses an image for the other revision”Cause: The image was built for the other board revision (… is a v1 board and the image is v2 -- the wrong pinout leaves it rebooting).
Fix: Set the board’s real revision, build for it and flash.
idf.py board --set v1idf.py -B build_v1 -DSDKCONFIG=sdkconfig.v1 buildpython3 tools/ota_flash.pySwap in v2 and its folders if the board is a v2. Do not use --force: an image for the other revision does not start on this board.
Delta update fails
Section titled “Delta update fails”Cause: --base-fw is not the exact image the board runs, so the patch does not apply (Error: OTA_ERROR delta_… or Error: OTA_ERROR end_… after Sending: OTA_DELTA).
Fix: Send the full image instead, then keep a copy of it as the base for the next delta.
python3 tools/ota_flash.pycp build_v2/CrossPad.bin ~/crosspad-base.bin # v1 board: build_v1python tools\ota_flash.pyCopy-Item build_v2\CrossPad.bin $HOME\crosspad-base.bin # v1 board: build_v1Error: base firmware not found or --base-fw is required means the path is wrong or missing: pass the copy with --base-fw.
Switching back to the previous firmware is refused
Section titled “Switching back to the previous firmware is refused”Cause: The running firmware has not confirmed itself yet (ERR running slot not confirmed yet), which takes 10 seconds after a flash.
Fix: Wait 10 seconds, list the slots and switch again.
crosspad-hil cdc FW_SLOTScrosspad-hil cdc FW_SWITCHIf the other slot shows state=empty or state=rolledback (ERR other slot is empty, ERR other slot did not start last time), there is nothing to go back to: flash the older image over OTA instead.
Board boot-loops after a flash
Section titled “Board boot-loops after a flash”Cause: An image for the wrong revision was forced onto it, or the new firmware does not start.
Fix: On a v2 board (PCB r20), load ESP-IDF in this terminal (idf.py must be on PATH), then re-flash everything over the STM32 bridge port with the v2 build.
python3 tools/bench.py recover --build build_v2python3 -m serial.tools.list_ports -vpython3 tools/bench.py recover --build build_v2 --port <port>python -m serial.tools.list_ports -vpython tools\bench.py recover --build build_v2 --port COMxcrosspad-hil finds the bridge port; without it, and on macOS and Windows, pass --port with the port whose USB ID is 0483:5740.
A v1 board (PCB r16 / r19) is recovered on the ESP’s own USB port instead. Put it into its ROM bootloader with requestBootloader.py, then flash the build_v1 images on the ESP’s own USB port, as in Flash or recover over UART, steps 4 and 5. Build build_v1 first if it is empty; the v2 build does not start on this board. If the board cannot start its USB connection, see the board does not enter its bootloader.
Serial port is busy
Section titled “Serial port is busy”Cause: Another program holds the port, such as an open idf.py monitor or a serial terminal (Could not exclusively lock port or the port is busy or doesn't exist, or on Windows Access is denied).
Fix: Close every monitor (Ctrl+] leaves idf.py monitor), unplug and replug the board, then check it is listed.
crosspad-hil devicesRun the step that failed again.
esptool cannot connect over UART
Section titled “esptool cannot connect over UART”Cause: The flash used the wrong port, or the auto-reset did not put the chip into its bootloader (Failed to connect to ESP32-S3: No serial data received.).
Fix: On a v2 board, use the STM32 bridge port, USB ID 0483:5740.
python3 -m serial.tools.list_ports -vidf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 -p <port> -b 460800 flashpython -m serial.tools.list_ports -vidf.py -B build_v2 "-DSDKCONFIG=sdkconfig.v2" -p COMx -b 460800 flashIf it still cannot sync, hold BOOT while you reset the board and run the flash again.
A v1 board is not flashed through the bridge port, because its STM32 firmware does not drive the ESP’s reset and boot pins. Send it a bootloader request, then flash the build_v1 images on the port the request prints (the ESP’s own ROM USB port), as in Flash or recover over UART, steps 4 and 5.
python3 tools/requestBootloader.py --method cdc,midipython tools\requestBootloader.py --method cdc,midiIf the request fails: the board does not enter its bootloader.
The STM32 bridge port is not listed
Section titled “The STM32 bridge port is not listed”Cause: The cable is charge-only or the board is off, so no USB device with VID:PID=0483:5740 appears.
Fix: Use a data cable, switch the board on, unplug and replug it, then list the ports again.
python3 -m serial.tools.list_ports -vpython -m serial.tools.list_ports -vIf it stays missing while the board runs, the STM32 firmware is not running, and dfu_flash.py --enter cannot reach it: it asks the STM32 through the ESP, and a stopped STM32 does not answer. Flash it over SWD: Flash the STM32, steps 2 to 5.
A v1 board does not enter its bootloader
Section titled “A v1 board does not enter its bootloader”Cause: Another program holds the board’s port, or the board is off or unplugged, so the request does not arrive (✗ Failed to send bootloader request via any method or ⚠ Device did not enter bootloader mode within … seconds).
Fix: Close every monitor, unplug and replug the board, and send the request again.
python3 tools/requestBootloader.py --method cdc,midipython tools\requestBootloader.py --method cdc,midiIf the board cannot start its USB connection, no request can reach it: wire a USB-UART adapter to ESP UART0 (TX, RX, GND) as in Flash or recover over UART. A three-wire adapter cannot reset the chip, so hold BOOT (IO0 to GND) while you reset the ESP to enter its bootloader.
No boot log on the console
Section titled “No boot log on the console”Cause: The monitor is on the ESP’s own USB port (303A:3456) instead of the STM32 bridge port (0483:5740), or it does not run at 115200 baud.
Fix:
python3 -m serial.tools.list_ports -vidf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 -p <port> monitorpython -m serial.tools.list_ports -vidf.py -B build_v2 "-DSDKCONFIG=sdkconfig.v2" -p COMx monitorPick the port with VID:PID=0483:5740; other serial terminals must use 115200 baud. If it stays silent on the right port, the STM32 firmware may not be running: unplug and replug the board.
App icon is blank after OTA
Section titled “App icon is blank after OTA”Cause: OTA writes only the firmware; app icons, the bundled STM32 image and the on-board docs live in the assets partition, which OTA never touches.
Fix:
python3 tools/fs_transfer.py assetspython tools\fs_transfer.py assetsA UART flash writes the assets partition as well.
STM32 firmware clone fails
Section titled “STM32 firmware clone fails”Cause: An earlier clone left the folder behind (fatal: destination path 'CrossPad_STM32_r2' already exists and is not an empty directory.), or the network dropped.
Fix: In the folder you ran git clone in, list your own changes in the clone and update it:
git -C CrossPad_STM32_r2 status --short --branchgit -C CrossPad_STM32_r2 pullgit -C CrossPad_STM32_r2 status --short --branchgit -C CrossPad_STM32_r2 pullIf pull worked, the clone is fine: go on with the build and skip the next block.
Only if pull failed: status shows your own changed files and, after ahead, commits that exist only in this clone. Keep them by moving the folder aside instead of deleting it, then clone again (replace /path/to/parent with the folder that holds CrossPad_STM32_r2):
cd /path/to/parent && mv CrossPad_STM32_r2 CrossPad_STM32_r2.old && git clone https://github.com/CrossPad/CrossPad_STM32_r2.gitcd C:\path\to\parentif ($?) { Rename-Item CrossPad_STM32_r2 CrossPad_STM32_r2.old; git clone https://github.com/CrossPad/CrossPad_STM32_r2.git }STM32 build cannot find arm-none-eabi-gcc or stops at flash_guard
Section titled “STM32 build cannot find arm-none-eabi-gcc or stops at flash_guard”Cause: arm-none-eabi-gcc is not on PATH in this terminal, so CMake cannot find the C compiler.
Fix: Put the 14.3.x compiler on PATH, then build again from a clean folder in CrossPad_STM32_r2. Replace /path/to with where you cloned it and where the toolchain is.
cd /path/to/CrossPad_STM32_r2export PATH=/path/to/arm-gnu-toolchain-14.3/bin:$PATHarm-none-eabi-gcc --versionrm -rf build/Debugcmake --preset Debugcmake --build build/Debugcd C:\path\to\CrossPad_STM32_r2$env:Path = "C:\path\to\arm-gnu-toolchain-14.3\bin;" + $env:Patharm-none-eabi-gcc --versionRemove-Item -Recurse -Force build\Debugcmake --preset Debugcmake --build build/DebugIf the build stops with flash_guard: firmware is … B and reaches the NVM region, check that --version prints 14.3.x, because an older compiler makes a larger image; with the right compiler, the image itself grew and the message says by how many bytes.
STM32 shows no link in Settings
Section titled “STM32 shows no link in Settings”Cause: The STM32 is not running its firmware or does not answer the ESP, so Settings → Programming shows STM32 running as no link and offers no Update or Reflash button.
Fix: Build and flash the STM32 yourself over SWD, as in Flash the STM32, steps 2 to 5. USB DFU with --enter (step 6) asks the STM32 over the same link that shows no link, so it cannot reach it.
STM32_Programmer_CLI cannot connect over SWD
Section titled “STM32_Programmer_CLI cannot connect over SWD”Cause: The ST-Link is not found: it is unplugged, or its driver (Windows) or udev rules (Linux) are missing (Error: No debug probe detected.).
Fix: Replug the ST-Link, install the driver or udev rules that come with STM32CubeProgrammer, check the SWD wires and board power, then run the same command again.
STM32_Programmer_CLI -c port=SWD freq=4000 -w build/Debug/CrossPad_STM32_r20.bin 0x08000000 -rst --start 0x08000000Error: No STM32 target found! means the probe works but cannot see the chip: check the SWD wiring and power, and keep the command unchanged, without mode=HOTPLUG.
STM32 DFU flash fails
Section titled “STM32 DFU flash fails”Cause: The board’s USB mode has no ESP serial port, so --enter cannot ask the STM32 to switch to DFU (no CrossPad CDC (303a:3456) — board off, or already in DFU?).
Fix: On the board, switch Settings → USB → Mode → MIDI + Serial and run the script again; if it says STM32_Programmer_CLI not found, put the CLI on PATH or set STM32_PROG to it.
export STM32_PROG=/path/to/STM32_Programmer_CLIpython3 tools/dfu_flash.py --enter$env:STM32_PROG = "C:\path\to\STM32_Programmer_CLI.exe"python tools\dfu_flash.py --enterIf it ends with the VCP did not come back within 15 s or stops partway, replug the board and run the same command again; an interrupted flash restarts in DFU mode, so the second run completes it.
Checks and tests
Section titled “Checks and tests”Doctor reports things to fix
Section titled “Doctor reports things to fix”Cause: The board is unplugged or its USB serial mode is off (No CrossPad found — plug it in over USB…), or the ESP-IDF path is not recorded (ESP-IDF not found); the doctor ends with N thing(s) to fix.
Fix: Do what each [BAD] row says (and the -> line under it, where there is one), then run the doctor again.
On a new board, the USB serial guard row is a note, not an error. It is the “USB serial mode?” safety prompt you answered with Allow during the first flash. Leave it on; Check it works explains it.
python3 tools/app_manager.py doctorpython tools\app_manager.py doctorSwitch USB serial on at the board under Settings → USB → Mode → MIDI + Serial. For “ESP-IDF not found”, write crosspad.local.json again.
Smoke test prints MISSING MARKER, FATAL or BOOT LOOP
Section titled “Smoke test prints MISSING MARKER, FATAL or BOOT LOOP”Cause: The smoke test found a problem in the boot log: the output shows MISSING MARKER:, ERROR LINE:, FATAL: or BOOT LOOP:, then HIL SMOKE: FAIL (exit code 1).
Fix: Read the newest report and the boot log.
cat "$(ls -td hil_logs/smoke_* | head -1)/report.json"Get-Content "$((Get-ChildItem hil_logs -Directory -Filter smoke_* | Sort-Object LastWriteTime)[-1].FullName)\report.json"The report is hil_logs/smoke_…/report.json in the folder you ran the test from. Fix the firmware, then build, flash and test again:
idf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 buildpython3 tools/ota_flash.pycrosspad-hil run smokeSmoke test says No boot banner on the console port
Section titled “Smoke test says No boot banner on the console port”Cause: The test setup, not the firmware, failed: crosspad-hil read a port that is not the STM32 bridge port (0483:5740), or the board did not start (exit code 2).
Fix:
crosspad-hil devicescrosspad-hil run smokeCheck that devices lists the board with its console port. If not, unplug and replug the board and check the boot log.
Smoke test stops with environment: NO_DEVICE or PORT_BUSY
Section titled “Smoke test stops with environment: NO_DEVICE or PORT_BUSY”Cause: crosspad-hil finds no board (unplugged, or on Linux no serial port permission), or another program or test holds the port (exit code 2).
Fix:
crosspad-hil doctorcrosspad-hil devicescrosspad-hil run smokeClose any open monitor and replug the board. On Linux, check serial port permissions.
Audio or BLE scenarios say sounddevice is unavailable or bleak is not installed
Section titled “Audio or BLE scenarios say sounddevice is unavailable or bleak is not installed”Cause: crosspad-hil was installed without its audio and BLE extras.
Fix: Install it again with all extras.
~/CrossPad/.venv/bin/pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"C:\CrossPad\firmware\.venv\Scripts\pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"On Linux, the audio scenarios also need PortAudio: sudo apt-get install -y libportaudio2.
diagnose says the ELF does not match the log
Section titled “diagnose says the ELF does not match the log”Cause: The ELF is from a different build than the firmware on the board, so its SHA256 differs from the ELF file SHA256 in the log and diagnose prints elf: … (DOES NOT match the log).
Fix: Pass the ELF of the build you flashed, or leave out --elf so diagnose picks the build whose SHA256 matches.
crosspad-hil diagnose --elf build_v2/CrossPad.elf # v1 board: build_v1crosspad-hil diagnoseIf no build matches, the build was overwritten since the flash: build, flash again and reproduce the problem.
Simulator
Section titled “Simulator”CMake cannot find SDL2, ALSA or DBus
Section titled “CMake cannot find SDL2, ALSA or DBus”Cause: The development libraries are missing, or on Windows the build ran without the vcpkg toolchain.
Fix:
sudo apt-get updatesudo apt-get install -y build-essential cmake ninja-build git pkg-config libsdl2-dev libasound2-dev libpulse-dev libdbus-1-devcd ~/crosspad-pcrm -rf buildcmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug && cmake --build buildbrew install sdl2 cmake ninja pkg-configcd ~/crosspad-pcrm -rf buildcmake -B build -G Ninja -DCMAKE_PREFIX_PATH=$(brew --prefix) -DUSE_BLE=OFFcmake --build buildIn x64 Native Tools Command Prompt for VS 2022:
cd /d C:\crosspad-pcrmdir /s /q buildcmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DCMAKE_BUILD_TYPE=Debugcmake --build buildWithout DBus on Linux, add -DUSE_BLE=OFF to the first cmake line. On Windows, if SDL2 is still not found, install it with vcpkg.
build.bat cannot find vcvarsall (Windows)
Section titled “build.bat cannot find vcvarsall (Windows)”Cause: build.bat expects VS 2022 Community; with only the Build Tools installed, build in the Native Tools prompt.
Fix: Build by hand in x64 Native Tools Command Prompt for VS 2022.
cd /d C:\crosspad-pcrmdir /s /q buildcmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DCMAKE_BUILD_TYPE=Debugcmake --build buildLook for Copying SDL2.dll to output directory; the build must end without error.
Simulator window does not open
Section titled “Simulator window does not open”Cause: There is no desktop session (SSH or headless), or SDL2.dll is not next to the exe.
Fix: Start it from a terminal on your desktop, not over SSH.
./bin/CrossPaddir bin\SDL2.dllbin\CrossPad.exeIf SDL2.dll is missing, build again from the x64 Native Tools prompt with the vcpkg toolchain. Look for [Remote] Listening on 127.0.0.1:19840 to confirm it started.
Simulator stops at start with RtMidiError or DBusException
Section titled “Simulator stops at start with RtMidiError or DBusException”Cause: On Linux the simulator needs the ALSA sequencer for MIDI and the system D-Bus for Bluetooth MIDI (BlueZ). A desktop Linux has both; a VM, WSL, a server or a container often has neither. The terminal shows one of:
terminate called after throwing an instance of 'RtMidiError'withMidiOutAlsa::initialize: error creating ALSA sequencer client object: there is no/dev/snd/seq.SimpleDBus::Exception::DBusExceptionwithFailed to connect to socket /run/dbus/system_bus_socket: no system D-Bus is running.The name org.bluez was not provided by any .service files: D-Bus runs, BlueZ is not installed.
Fix: For the sequencer, run the simulator where /dev/snd/seq exists (load the snd-seq kernel module, or in a container pass --device /dev/snd/seq), or build it without MIDI (-DUSE_MIDI=OFF). For D-Bus and BlueZ, either install and start them (sudo apt-get install dbus bluez), or build without Bluetooth MIDI, as the macOS tab does:
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DUSE_BLE=OFFcmake --build buildSimulator says Failed to bind port
Section titled “Simulator says Failed to bind port”Cause: Another simulator already holds port 19840, so this copy opens without remote control ([Remote] Failed to bind port 19840) and the MCP tools keep talking to the first one.
Fix: Close every copy, then start one.
pkill -f bin/CrossPad./bin/CrossPadtaskkill /IM CrossPad.exe /Fbin\CrossPad.exeThe new copy prints [Remote] Listening on 127.0.0.1:19840.
vcpkg cannot install SDL2
Section titled “vcpkg cannot install SDL2”Cause: The C++ build tools are not installed yet, or vcpkg was not bootstrapped.
Fix:
C:\vcpkg\bootstrap-vcpkg.bat -disableMetricsC:\vcpkg\vcpkg install sdl2:x64-windowsInstall the VS 2022 Build Tools first, as on the PC simulator page. Keep vcpkg in C:\vcpkg, a path without spaces.
idf.py says app-list is not known
Section titled “idf.py says app-list is not known”Cause: idf.py ran outside the CrossPad project root, where the app-* commands do not exist (command "app-list" is not known to idf.py, or CMakeLists.txt not found in project directory).
Fix:
cd ~/CrossPadidf.py app-listcd C:\CrossPad\firmwareidf.py app-listInstaller users can run crosspad-idf app-list from any folder.
A new app does not show up
Section titled “A new app does not show up”Cause: The build folder predates the install, so the app list compiled into the build does not include the new app. This holds for the board (the MODE map) and for the simulator (its launcher).
Fix on the board:
idf.py -B build_v2 fullcleanidf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 buildWhile CMake configures, Generated app_registry_init.cpp with N apps lists every app; check yours is there, then flash again.
Fix in the simulator: Build again from its folder, so CMake configures again and finds the app in src/apps.
cd ~/crosspad-pccmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug && cmake --build buildapp-update skips an app: on master, config says main
Section titled “app-update skips an app: on master, config says main”Cause: The app was recorded on main, but its repository’s default branch is master (for example sampler and synthesizer).
Fix: Install the app again on its real branch.
idf.py app-remove --app sampleridf.py app-install --app sampler --ref masterDo the same for any app whose repository’s default branch is master. More: Install and remove apps.
app-list says No connection
Section titled “app-list says No connection”Cause: The catalog could not be downloaded and there is no saved copy (app-registry.json in the project folder) yet, so app-list prints No connection, and no app list saved on this computer yet. and exits with code 1.
Fix: Connect to the internet, then list again from the project folder.
idf.py app-listAfter one successful run, the saved copy is used when there is no connection, and refreshed when it is more than an hour old.
app-install says Failed to add submodule
Section titled “app-install says Failed to add submodule”Cause: git could not clone the app’s repository (Error: Failed to add submodule. Check repo URL and network.), because there is no network or you have no read access to that repo.
Fix: Check that the repo from the Repo: line answers and that the id is in the list (Error: Unknown app '…'. means a misspelled id).
git ls-remote <repo url from the Repo: line>idf.py app-listFor an app outside the catalog, add --origin <repo url> to app-install.
idf.py app-new stops with an error
Section titled “idf.py app-new stops with an error”Cause: An earlier run already made the app, so its folder is in the way (Error: components/crosspad-… already exists).
Fix: Remove the earlier app (if app-remove says it is not installed, delete its folder in components/ by hand), or pick another id made of lowercase letters, digits and dashes that starts with a letter.
idf.py app-remove --app my-appidf.py app-new --app my-app --name "My App"Error: app template unavailable means the template could not be downloaded from GitHub; check the connection or proxy and run it again.
Publishing says gh is not authenticated
Section titled “Publishing says gh is not authenticated”Cause: The GitHub CLI gh is not signed in, so app-new --public stops with Error: gh is not authenticated (gh auth login) and CP Tools with Couldn't: not signed in to GitHub.
Fix: Sign in, check it, then repeat the step.
gh auth logingh auth statusIf gh itself is not found, install the GitHub CLI from cli.github.com first.
CP Tools submit says Not yet
Section titled “CP Tools submit says Not yet”Cause: The app does not meet the catalog’s rules yet: each line under the Not yet: header names one problem, such as crosspad-app.json has no "platforms" or the repository is private — other people could not install it.
Fix: Fix every problem in the list, then submit again: complete crosspad-app.json and push it, make the repo public, and for the app has no GitHub repository publish it first as in Publish an app.
git -C components/crosspad-my-app commit -am "Complete the manifest"git -C components/crosspad-my-app pushgh repo edit you/crosspad-my-app --visibility public --accept-visibility-change-consequencesit is already in the catalog needs no submit: the app is listed already.
My app is not in the catalog
Section titled “My app is not in the catalog”Cause: The client still uses its saved catalog, app-registry.json in the project folder, which it refreshes only once an hour.
Fix: Delete the saved catalog and list again.
cd ~/CrossPadrm -f app-registry.jsonidf.py app-listgh repo view you/crosspad-my-app --json visibility,repositoryTopicscd C:\CrossPad\firmwareRemove-Item app-registry.json -ErrorAction SilentlyContinueidf.py app-listgh repo view you/crosspad-my-app --json visibility,repositoryTopicsStill missing: the catalog rebuilds every six hours, when an org app publishes a release and when an external-apps.json pull request is merged. It skips a repo whose crosspad-app.json on GitHub is missing or is not valid JSON, and an org repo without the topic crosspad-app.
File transfer says FS_ERR mount
Section titled “File transfer says FS_ERR mount”Cause: The board could not mount the internal /spiflash volume the path names (a missing SD card shows up as FS_ERR open_…, mkdir_… or stat_… with an error number instead).
Fix: See which volumes are mounted: a - under total means that one is not.
python3 tools/fs_transfer.py rootspython tools\fs_transfer.py rootsFor /sdcard, insert a FAT-formatted card and restart the board; for errors on /sdcard paths, see file transfer says FS_ERR mkdir or FS_ERR open. For /spiflash, restart the board and run the command again. If it still fails, watch the console while you run it: the board prints storage mount failed there while you run the command.
File transfer says FS_ERR mkdir or FS_ERR open
Section titled “File transfer says FS_ERR mkdir or FS_ERR open”Cause: The board could not create a folder or file under /sdcard (Device error: FS_ERR mkdir_… or Device error: FS_ERR open_…, with an error number), because no card is in, the card is not FAT-formatted, or a parent folder such as /sdcard/crosspad/kits does not exist yet on a blank card.
Fix: Check that the card is mounted: /sdcard must show numbers under total, not -.
python3 tools/fs_transfer.py rootspython tools\fs_transfer.py rootsIf it shows -, insert a FAT-formatted card and restart the board. Then create the missing folders one level at a time, because mkdir makes only the last folder of the path:
python3 tools/fs_transfer.py mkdir /sdcard/crosspadpython3 tools/fs_transfer.py mkdir /sdcard/crosspad/kitspython tools\fs_transfer.py mkdir /sdcard/crosspadpython tools\fs_transfer.py mkdir /sdcard/crosspad/kitsEach line prints Created and the folder. FS_ERR mkdir_17 means that folder exists already, which is fine. Then run the transfer again.
Pitched kit is missing from the kit list
Section titled “Pitched kit is missing from the kit list”Cause: The board reads the kit list when it starts, so a kit copied since the last restart appears after a restart.
Fix: Restart the board; if the kit is still missing, check that kit.json sits in its own folder under /sdcard/crosspad/kits and is valid JSON with "engine": "pitched", then push it again.
python3 tools/fs_transfer.py ls /sdcard/crosspad/kits/PIANOpython3 -m json.tool kit.jsonpython tools\fs_transfer.py ls /sdcard/crosspad/kits/PIANOpython -m json.tool kit.jsonFor the test kit of Play a pitched instrument, step 1, run python3 tools/make_pitched_kit.py --zones 2 again and restart the board.
Every claude mcp add below replaces the whole crosspad entry, including the --env settings it had. Run claude mcp get crosspad first to see what is set now, and repeat every setting you still need on the new add line. The two --env fixes below use one combined line, so following both keeps both: keep CROSSPAD_HIL_PYTHON if you use the HIL tools, keep CROSSPAD_IDF_ROOT and IDF_PATH if your project is in ~/CrossPad, and add any other --env that get showed.
Claude shows no crosspad tools
Section titled “Claude shows no crosspad tools”Cause: The server is not registered, it was registered with npx instead of node (MCP error -32000: Connection closed), or only the Claude Code plugin is installed, which brings skills but no runnable server.
Fix: Install the server locally and register it with node.
node --versionnpm i --prefix ~/.local/crosspad-mcp crosspad-mcp-server@latestclaude mcp remove crosspadclaude mcp add -s user crosspad -- node ~/.local/crosspad-mcp/node_modules/crosspad-mcp-server/dist/index.jsYou need Node.js 18 or newer; restart Claude Code afterwards. Keep the plugin for its skills. If claude mcp get crosspad showed --env settings, add them to the add line before the --.
crosspad tools only work in one folder
Section titled “crosspad tools only work in one folder”Cause: claude mcp add without -s user registers the server for the current folder only.
Fix:
claude mcp remove -s local crosspadclaude mcp add -s user crosspad -- node ~/.local/crosspad-mcp/node_modules/crosspad-mcp-server/dist/index.jsclaude mcp listRestart Claude Code; the server now starts in every folder. If claude mcp get crosspad showed --env settings, add them to the add line before the --.
An MCP update does not take effect
Section titled “An MCP update does not take effect”Cause: Claude Code starts the server once per session and keeps it in memory, so a newer version on disk is not used yet.
Fix:
npm i --prefix ~/.local/crosspad-mcp crosspad-mcp-server@latestRestart Claude Code (or reload the window) after every update. Check the version in the server’s start-up line, crosspad-mcp v… policy=….
HIL tools say crosspad-hil is missing
Section titled “HIL tools say crosspad-hil is missing”Cause: The server runs crosspad-hil with python3 unless told otherwise, and that interpreter does not have it.
Fix: Point the server at the project’s .venv with CROSSPAD_HIL_PYTHON. The combined line also keeps the folders from crosspad tools cannot find the project or ESP-IDF; see the note at the top of this section for which --env to keep.
claude mcp get crosspadHIL_PY=~/CrossPad/.venv/bin/pythonPROJ=~/CrossPadclaude mcp remove -s user crosspadclaude mcp add -s user crosspad --env CROSSPAD_HIL_PYTHON=$HIL_PY --env CROSSPAD_IDF_ROOT=$PROJ --env IDF_PATH=$CROSSPAD_IDF_DIR -- node ~/.local/crosspad-mcp/node_modules/crosspad-mcp-server/dist/index.jsOn Windows use .venv\Scripts\python.exe in the project folder. Then restart Claude Code: the server reads the variable only when it starts (set it with the variable, as above).
crosspad tools cannot find the project or ESP-IDF
Section titled “crosspad tools cannot find the project or ESP-IDF”Cause: The server looks for repos under ~/GIT and for ESP-IDF in ~/esp/esp-idf, so a project in ~/CrossPad or an ESP-IDF in ~/esp/esp-idf-v5.5 is not found.
Fix: Tell the server where both are with CROSSPAD_IDF_ROOT and IDF_PATH. The combined line also keeps CROSSPAD_HIL_PYTHON from HIL tools say crosspad-hil is missing; see the note at the top of this section for which --env to keep.
claude mcp get crosspadHIL_PY=~/CrossPad/.venv/bin/pythonPROJ=~/CrossPadclaude mcp remove -s user crosspadclaude mcp add -s user crosspad --env CROSSPAD_HIL_PYTHON=$HIL_PY --env CROSSPAD_IDF_ROOT=$PROJ --env IDF_PATH=$CROSSPAD_IDF_DIR -- node ~/.local/crosspad-mcp/node_modules/crosspad-mcp-server/dist/index.jsRestart Claude Code afterwards.
If all your CrossPad repos share one parent folder, set CROSSPAD_GIT_DIR to it instead. Ask Claude to read the crosspad://workspace resource to see what the server found.
Build in Claude Code fails with a bare repository error
Section titled “Build in Claude Code fails with a bare repository error”Cause: Claude Code runs commands with safe.bareRepository=explicit, and the ESP-IDF component manager’s git cache trips on it ('git config --get remote.origin.url' failed with exit code 1).
Fix: Override the setting for that one command.
GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=safe.bareRepository GIT_CONFIG_VALUE_0=all idf.py -B build_v2 -DSDKCONFIG=sdkconfig.v2 buildThe crosspad_build platform=idf tool sets this for you. If that tool fails the same way, update the server and restart Claude Code.