Repository navigation
Common_issues
This guide covers the most frequently encountered problems when working with painlessMesh and their solutions.
Symptoms:
- HTTP/HTTPS requests fail with "connection refused"
-
WiFi.status()shows disconnected on regular mesh nodes - Internet services (APIs, WhatsApp bot, etc.) only work on bridge node
Cause:
This is expected behavior, not a bug. Only bridge nodes have internet access.
Solution:
See the dedicated guide for this common architecture mistake:
📖 Common Architecture Mistakes
Quick Summary:
painlessMesh uses a bridge-forwarding pattern:
- Bridge node: Has internet access, forwards data to/from internet
- Regular nodes: No internet access, send data to bridge
- Architecture: Regular nodes → Bridge → Internet
Regular nodes must send data to the bridge, which then forwards to internet services.
Symptoms:
- Device crashes immediately after mesh initialization
- Endless reboot loop
- Error message:
assert failed: tcp_alloc ... (Required to lock TCPIP core functionality!)
Solution:
This is a known compatibility issue with ESP32-C6 and newer ESP32 variants. See the dedicated guide:
📖 ESP32-C6 Compatibility Guide
Quick Fix: Update your AsyncTCP library to version 3.3.0 or newer, or use the ESP32Async library which includes proper LWIP locking for Arduino ESP32 core 3.1.0+.
For PlatformIO, add to your platformio.ini:
lib_deps =
esp32async/AsyncTCP @ ^3.4.7For Arduino IDE, download and install manually from: https://github.com/ESP32Async/AsyncTCP
Symptoms:
- Phone or computer can't see the mesh WiFi network
- Can see network but can't connect
- Connected but no IP address assigned
- Connection drops frequently
Solution:
See the dedicated guide for connecting external devices:
📖 Connecting External Devices Guide
Quick Summary:
External devices (phones, computers, test equipment) can connect to the bridge node's WiFi AP for debugging:
- SSID: Your MESH_PREFIX value
- Password: Your MESH_PASSWORD value
- IP Range: 10.x.x.x/24 (DHCP automatic)
- Limits: ESP32 supports 10 devices, ESP8266 supports 4
Common issues are DHCP timing, channel changes, and connection limits.
Symptoms:
- Nodes don't appear in each other's node lists
- No "New Connection" messages in serial output
- Mesh remains disconnected
Solutions:
Ensure all nodes use identical network settings:
// These MUST be identical on all nodes
#define MESH_PREFIX "MyMeshNetwork" // Exact match required
#define MESH_PASSWORD "password123" // Case sensitive
#define MESH_PORT 5555 // Must match- Nodes must be within WiFi range (typically 50-200m)
- Check for interference from other 2.4GHz devices
- Try moving nodes closer together for testing
Enable connection debugging:
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);Look for error messages like:
- "Failed to connect to mesh"
- "Connection timeout"
- "Authentication failed"
Clear stored WiFi credentials:
void setup() {
// Add this before mesh.init()
WiFi.disconnect(true); // Clear stored networks
delay(1000);
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
}Symptoms:
- Nodes connect but disconnect shortly after
- Repeated "Connection dropped" messages
- Unstable mesh topology
Solutions:
- Ensure stable power supply (USB power can be insufficient)
- Use adequate power adapters (≥1A for ESP32, ≥500mA for ESP8266)
- Check for voltage drops during WiFi transmission
Limit the number of simultaneous connections:
// Reduce connection count on ESP8266
#define MAX_CONN 2 // Instead of default 4// Extend connection timeouts
#define CONNECTION_TIMEOUT 60000 // 60 seconds instead of 30Monitor memory usage:
void checkMemory() {
Serial.printf("Free heap: %d bytes\n", ESP.getFreeHeap());
if (ESP.getFreeHeap() < 10000) { // ESP32
Serial.println("WARNING: Low memory!");
}
}Symptoms:
- Serial output shows:
tcp_err(): error trying to connect -14 - Nodes get an IP address but fail to establish mesh connection
- Connection attempts keep failing and retrying
Cause:
The error -14 (ERR_CONN in LwIP) indicates a TCP connection failure. This typically occurs when:
- The TCP server on the target node is not ready when the connection is attempted
- There's a timing issue between WiFi association and TCP readiness
- Network stack hasn't fully stabilized after IP acquisition
- The target node is overloaded or has resource constraints
Solutions:
The error often occurs with older AsyncTCP versions that don't have proper thread safety for ESP32 Arduino Core 3.x:
For PlatformIO:
lib_deps =
esp32async/AsyncTCP @ ^3.4.7For Arduino IDE, install manually from: https://github.com/ESP32Async/AsyncTCP
painlessMesh now includes automatic TCP connection retry with the following behavior:
- Up to 6 total connection attempts (initial + 5 retries)
- Exponential backoff delays between retries: 1s, 2s, 4s, 8s, 8s (total ~23s)
- 500ms stabilization delay after IP acquisition before first connection attempt
- Full WiFi reconnection with 10s delay only triggered after all retries are exhausted
This exponential backoff helps handle transient timing issues automatically while reducing network congestion from multiple retrying nodes.
Monitor memory and ensure nodes aren't overloaded:
void loop() {
mesh.update();
// Monitor health periodically
static unsigned long lastCheck = 0;
if (millis() - lastCheck > 10000) {
lastCheck = millis();
Serial.printf("Free heap: %d, WiFi RSSI: %d\n",
ESP.getFreeHeap(), WiFi.RSSI());
}
}Make sure the mesh is properly initialized before connections are attempted:
void setup() {
Serial.begin(115200);
delay(100); // Let serial initialize
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
// Add callbacks after init
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
}Poor signal can cause connection timing issues:
- Ensure nodes are within good WiFi range
- Check for interference from other 2.4GHz devices
- Monitor RSSI values (should be above -80 dBm for reliable connections)
Symptoms:
-
sendBroadcast()returnstruebut messages don't arrive - Callbacks not triggered
- Silent message failures
Solutions:
Ensure callbacks are set before mesh.init():
void setup() {
Serial.begin(115200);
// Set callbacks BEFORE init
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
// Then initialize
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
}Check JSON formatting for custom messages:
void sendSensorData() {
// Proper JSON formatting
String msg = "{";
msg += "\"type\":\"sensor\",";
msg += "\"value\":" + String(sensorValue) + ",";
msg += "\"timestamp\":" + String(mesh.getNodeTime());
msg += "}"; // Don't forget closing brace
mesh.sendBroadcast(msg);
}mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION | COMMUNICATION);Reduce message frequency if network is congested:
// Instead of every second
Task taskSendMessage(10000, TASK_FOREVER, &sendMessage); // Every 10 secondsSymptoms:
- Small messages work, large ones don't
- Memory errors in serial output
- Random message failures
Solutions:
// Keep messages under 1KB for reliability
String createMessage() {
String msg = "{\"data\":\"";
msg += shortData; // Keep data concise
msg += "\"}";
if (msg.length() > 1000) {
Serial.println("Warning: Message too large");
return "{}"; // Send empty object
}
return msg;
}void sendLargeData(String largeData) {
const size_t chunkSize = 500;
for (size_t i = 0; i < largeData.length(); i += chunkSize) {
String chunk = largeData.substring(i, i + chunkSize);
String msg = "{\"chunk\":" + String(i/chunkSize) + ",\"data\":\"" + chunk + "\"}";
mesh.sendBroadcast(msg);
delay(100); // Small delay between chunks
}
}Symptoms:
- Frequent crashes or resets
- "Out of memory" errors
- Unstable behavior under load
Solutions:
// Use smaller JSON documents
DynamicJsonDocument doc(512); // Instead of 1024 or larger
// Limit string sizes
TSTRING deviceName;
deviceName.reserve(32); // Pre-allocate reasonable size#define MAX_CONN 2 // ESP8266 works best with 2-3 connections// Combine multiple tasks into one
Task taskMultiFunction(30000, TASK_FOREVER, [](){
sendSensorData();
checkStatus();
cleanupMemory();
});void monitorMemory() {
uint32_t freeHeap = ESP.getFreeHeap();
Serial.printf("Free heap: %u bytes\n", freeHeap);
if (freeHeap < 5000) { // Critical threshold for ESP8266
Serial.println("CRITICAL: Very low memory!");
// Take corrective action
mesh.stop();
delay(1000);
ESP.restart();
}
}Symptoms:
- Slower performance over time
- Memory leaks
- Task watchdog timeouts
Solutions:
void checkHeapHealth() {
Serial.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
Serial.printf("Largest block: %u bytes\n", ESP.getMaxAllocHeap());
// If largest block is much smaller than free heap,
// heap is fragmented
if (ESP.getMaxAllocHeap() < ESP.getFreeHeap() / 2) {
Serial.println("Warning: Heap fragmentation detected");
}
}// Instead of dynamic allocation
StaticJsonDocument<1024> doc; // Pre-allocated
// Or use stack allocation for small objects
char buffer[256];
snprintf(buffer, sizeof(buffer), "{\"value\":%d}", value);Symptoms:
- "painlessMesh.h: No such file or directory"
- Library compilation errors
Solutions:
- Go to Sketch → Include Library → Manage Libraries
- Search for "painlessMesh" and install latest version
- Ensure ArduinoJson and TaskScheduler are also installed
Add to platformio.ini:
lib_deps =
painlessMesh
bblanchon/ArduinoJson@^6.21.3
arkhipenko/TaskScheduler@^3.7.0Symptoms:
- Compilation errors after library updates
- API function not found errors
- Deprecated warnings
Solutions:
// Check painlessMesh version
#include "painlessMesh.h"
Serial.printf("painlessMesh version: %s\n", PAINLESSMESH_VERSION);In platformio.ini:
lib_deps =
painlessMesh@1.5.0 # Lock to specific version
bblanchon/ArduinoJson@6.21.3
arkhipenko/TaskScheduler@3.7.0// Old API (deprecated)
mesh.onReceive(&receivedCallback);
// New API (if changed in your version)
mesh.onReceive([](uint32_t from, String& msg) {
receivedCallback(from, msg);
});Symptoms:
- Messages take several seconds to arrive
- High latency in mesh communication
- Sluggish response times
Solutions:
void printTopology() {
String topology = mesh.subConnectionJson(true);
Serial.println("Current topology:");
Serial.println(topology);
// Look for long chains or star topologies
// Optimal: balanced tree with short paths
}// Instead of high frequency
Task taskFastSender(1000, TASK_FOREVER, &sendMessage); // Every second
// Use lower frequency
Task taskSlowSender(10000, TASK_FOREVER, &sendMessage); // Every 10 seconds// Compact JSON formatting
String createOptimizedMessage() {
// Use short field names
String msg = "{\"t\":" + String(temp) + ",\"h\":" + String(hum) + "}";
return msg;
}Symptoms:
- ESP becomes hot during operation
- Watchdog timer resets
- Sluggish response to other tasks
Solutions:
void loop() {
mesh.update();
// Add small delay to prevent CPU overload
delay(10);
// Or yield to other tasks
yield();
}// Only use essential debug messages in production
mesh.setDebugMsgTypes(ERROR); // Only errors// Spread tasks over time
Task task1(30000, TASK_FOREVER, &function1); // Every 30s
Task task2(35000, TASK_FOREVER, &function2); // Every 35s (offset)
Task task3(40000, TASK_FOREVER, &function3); // Every 40sReset Loops:
// Increase watchdog timeout
ESP.wdtDisable();
// Perform long operations
ESP.wdtEnable(5000); // 5 second timeoutFlash Memory Issues:
// Check flash size
Serial.printf("Flash size: %u bytes\n", ESP.getFlashChipSize());
// Ensure adequate space for SPIFFS/LittleFS
// Reserve at least 64KB for filesystemCore Affinity:
// Pin mesh tasks to specific core if needed
void setup() {
// Use core 0 for mesh (core 1 for app)
xTaskCreatePinnedToCore(meshTask, "MeshTask", 8192, NULL, 1, NULL, 0);
}Partition Scheme: Ensure adequate partition sizes in partition table:
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x140000,
app1, app, ota_1, 0x150000,0x140000,
spiffs, data, spiffs, 0x290000,0x160000,
Enable comprehensive debugging:
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION | SYNC |
COMMUNICATION | GENERAL | MSG_TYPES | REMOTE);Look for patterns in the output:
- Repeated connection attempts
- Memory allocation failures
- Message transmission errors
- Time synchronization issues
Use WiFi monitoring tools:
- WiFi Analyzer apps to check channel congestion
- Router logs to see connection patterns
- Packet capture tools for advanced debugging
Add timing measurements:
void timedFunction() {
unsigned long start = millis();
// Your code here
performOperation();
unsigned long duration = millis() - start;
if (duration > 1000) { // Alert if > 1 second
Serial.printf("Slow operation: %lu ms\n", duration);
}
}If you're still experiencing issues:
- Check the FAQ for additional solutions
- Search existing issues on GitHub
-
Post in the community forum with:
- Complete serial output with debug enabled
- Hardware details (ESP32/ESP8266 model)
- Network topology (number of nodes, layout)
- Code snippets showing the problem
- Create a minimal test case that reproduces the issue
- Include library versions and platform information
- Start simple - Test with 2 nodes before scaling up
- Monitor resources - Check memory and CPU usage regularly
- Use version control - Track changes that might introduce issues
- Test incremental changes - Don't change everything at once
- Document your setup - Keep notes on working configurations
- Regular testing - Verify mesh operation after any changes
Remember: Most mesh networking issues are related to network configuration, power supply, or memory management. Check these fundamentals first before diving into complex debugging.