Before writing a single line of code, we need to clear up a common framework misconception: standard AVR Arduino boards (like the Uno or Nano) do not use the Preferences library. They use EEPROM.h. The Preferences API is strictly an ESP32 wrapper for Espressif’s Non-Volatile Storage (NVS) partition. If you are searching for how to delete a preferences namespace in Arduino, you are working with an ESP32, and you are interacting with a flash-based key-value store, not raw EEPROM bytes.

The direct answer: To wipe all keys and values inside a namespace, call prefs.clear(). However, this leaves the empty namespace header in the NVS dictionary. To physically delete the namespace structure from the flash partition and reclaim the overhead, you must drop down to the ESP-IDF C API using nvs_flash_erase_partition() or use the esptool to erase the entire NVS partition. For 99% of application resets, prefs.clear() is the correct tool. Use partition erasure only when debugging NVS corruption or reclaiming fragmented flash pages.

The Short Answer: Clearing vs. Deleting an ESP32 Namespace

The ESP32 NVS partition operates like a miniature file system. It uses a 4KB page structure with wear-leveling. When you call prefs.begin("my_app", false), the ESP32 allocates a namespace handle.

  • Clearing (prefs.clear()): Marks all key-value pairs within "my_app" as deleted. The data is gone, and your code will read default values. The namespace handle itself remains in the NVS dictionary.
  • Deleting (ESP-IDF C API): Strips the namespace entirely from the NVS blob. This is rarely necessary unless you are dynamically generating namespace names (which you shouldn't do, as it causes flash fragmentation) or hitting the maximum namespace limit.
  • Nuclear Option (esptool erase_flash): Wipes the entire 4MB/8MB/16MB flash chip, including your firmware, WiFi credentials, and NVS. Use this only when the NVS partition is fatally corrupted.
Bench Tip: Never use user input or dynamic strings as namespace names. The NVS dictionary has a hard limit on namespace entries. If you create and delete namespaces in a loop, you will exhaust the NVS index pages and trigger a StoreProhibited panic. Stick to hardcoded, compile-time namespace strings.

Hardware & Environment Spec Sheet

This guide and the accompanying code target the most common development board in the ecosystem. If you are using a custom PCB, ensure your SPI flash is correctly mapped.

ComponentSpecification / VariantNotes
MicrocontrollerESP32-WROOM-32 DevKit v1 (30-pin or 38-pin)Target board for Arduino IDE 2.x
Frameworkarduino-esp32 Core v2.0.14 or v3.0.xNVS API is stable across both
Flash Size4MB (Minimum)Requires "Default 4MB with spiffs" partition scheme
Status LEDOnboard GPIO 2 (or external LED)Indicates NVS write/erase status
Trigger ButtonOnboard BOOT button (GPIO 0)Pulled LOW to trigger namespace wipe

Pin Mapping Table

FunctionESP32 GPIOWiring Notes
Status LEDGPIO 2Active HIGH (onboard). Blink = NVS OK, Solid = Erased.
Erase TriggerGPIO 0Active LOW. Tied to onboard BOOT button. Internal pull-up enabled.

The Code: Wiping Preferences with Error Handling

The following sketch is fully compilable. It initializes a namespace, writes a boot counter, and monitors GPIO 0. When the BOOT button is pressed, it executes both the standard Arduino clear() method and the deep ESP-IDF partition erase method.

Board Variant Target: ESP32 Dev Module.
Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS).

#include <Preferences.h>
#include <nvs_flash.h>
#include <nvs.h>

// --- Pin Definitions ---
#define LED_PIN 2       // Onboard LED for status indication
#define ERASE_BTN_PIN 0 // Onboard BOOT button (Active LOW)

// --- NVS Configuration ---
#define NVS_NAMESPACE "my_app_data"
#define NVS_PARTITION "nvs"

Preferences prefs;
unsigned int bootCount = 0;

void setup() {
  Serial.begin(115200);
  delay(500); // Allow serial monitor to connect
  
  pinMode(LED_PIN, OUTPUT);
  pinMode(ERASE_BTN_PIN, INPUT_PULLUP);

  Serial.println("[BOOT] Initializing NVS Preferences...");

  // 1. Initialize Preferences with Error Handling
  // The second parameter 'false' means Read/Write mode
  bool beginSuccess = prefs.begin(NVS_NAMESPACE, false);
  
  if (!beginSuccess) {
    Serial.println("[ERROR] Failed to initialize NVS namespace. Flash may be corrupted.");
    Serial.println("[ACTION] Run 'esptool erase_flash' via terminal to recover.");
    // Blink LED rapidly to indicate fatal NVS failure
    while(1) {
      digitalWrite(LED_PIN, !digitalRead(LED_PIN));
      delay(100);
    }
  }

  // 2. Read and increment boot counter
  bootCount = prefs.getUInt("boot_count", 0);
  bootCount++;
  prefs.putUInt("boot_count", bootCount);
  
  Serial.printf("[INFO] Current Boot Count: %u\n", bootCount);
  Serial.println("[INFO] Hold BOOT button for 2 seconds to wipe namespace.");
  
  digitalWrite(LED_PIN, HIGH); // LED ON = NVS Active
}

void loop() {
  // Check if BOOT button is held down
  if (digitalRead(ERASE_BTN_PIN) == LOW) {
    unsigned long pressStart = millis();
    
    // Wait for 2-second long press to prevent accidental wipes
    while (digitalRead(ERASE_BTN_PIN) == LOW) {
      if (millis() - pressStart > 2000) {
        Serial.println("\n[WIPE] Button held. Executing Namespace Deletion...");
        digitalWrite(LED_PIN, LOW); // Turn off LED during erase
        
        executeNamespaceDeletion();
        
        Serial.println("[WIPE] Complete. Restarting ESP32 in 1 second...");
        delay(1000);
        ESP.restart();
      }
      delay(50);
    }
  }
  
  delay(100); // Main loop debounce
}

void executeNamespaceDeletion() {
  // METHOD A: The Arduino Wrapper Way (Clears keys, keeps namespace header)
  Serial.println("[STEP 1] Running prefs.clear()...");
  size_t clearedBytes = prefs.clear();
  Serial.printf("[STEP 1] Cleared %u bytes of key-value data.\n", clearedBytes);
  prefs.end(); // Always close the handle before low-level operations

  // METHOD B: The ESP-IDF Deep Erase (Wipes the entire NVS partition)
  // Use this ONLY if you need to reclaim fragmented pages or fix corruption.
  // WARNING: This deletes ALL namespaces (WiFi creds, other app data, etc.)
  Serial.println("[STEP 2] Executing deep NVS partition erase via ESP-IDF...");
  
  esp_err_t err = nvs_flash_deinit();
  if (err != ESP_OK) {
    Serial.printf("[WARN] nvs_flash_deinit failed: %s\n", esp_err_to_name(err));
  }
  
  err = nvs_flash_erase_partition(NVS_PARTITION);
  if (err == ESP_OK) {
    Serial.println("[SUCCESS] NVS partition erased at the flash level.");
  } else {
    Serial.printf("[ERROR] Partition erase failed: %s\n", esp_err_to_name(err));
  }
  
  // Re-initialize the partition so the ESP32 doesn't panic on reboot
  err = nvs_flash_init();
  if (err != ESP_OK) {
    Serial.printf("[FATAL] nvs_flash_init failed after erase: %s\n", esp_err_to_name(err));
  }
}

Debugging NVS Failures: Exact Errors and Ranked Causes

When working with flash memory, silent failures are rare; the ESP32 will usually dump a stack trace or an ESP-IDF error code to the Serial Monitor. If your prefs.begin() returns false or the ESP32 reboots unexpectedly, look for these exact strings.

Exact Error String: E (145) nvs: nvs_flash_init failed: ESP_ERR_NVS_NO_FREE_PAGES

This is the most common NVS error. It means the NVS partition has run out of clean 4KB pages to write new data or index entries, usually due to severe fragmentation from improper deletion loops.

The First Three Things to Check When It Fails:

  1. Partition Table Selection: Open Tools > Partition Scheme in the Arduino IDE. If you selected "No OTA (2MB APP/2MB SPIFFS)" but your code expects a specific NVS layout, the linker might map the NVS partition to an invalid address. Always verify the partition CSV matches your flash size.
  2. Namespace String Length: The ESP-IDF enforces a strict 15-character limit for namespace names and 15-character limit for keys. If you pass a 16-character string to prefs.begin(), it will silently fail or throw a StoreProhibited Guru Meditation Error. Count your characters.
  3. Flash Wear and Corruption: If the ESP32 lost power during a prefs.put() operation, the NVS page header might be corrupted. The ESP32 cannot perform garbage collection on a corrupted page, leading to the NO_FREE_PAGES error.

Ranked Causes of NVS Corruption

RankCauseSymptomFix
1Power loss during put() or commit()Reads return old data; subsequent writes fail.Call nvs_flash_erase_partition() and re-initialize.
2Dynamic namespace generation in a loopESP_ERR_NVS_NO_FREE_PAGES after a few hours.Refactor code to use a single namespace with structured keys.
3Incorrect Partition Scheme in Arduino IDEprefs.begin() returns false immediately on boot.Change to "Default 4MB with spiffs" and re-upload.
4Exceeding 15-character key/namespace limitGuru Meditation Error (LoadProhibited / StoreProhibited).Shorten string literals to ≤ 15 chars.

Decision Path: Which Erase Method Should You Use?

Do not guess when clearing flash memory. Use this decision tree to select the exact function required for your current debugging or production scenario.

Your ScenarioRequired ActionConcrete Tool / Function
User clicked "Factory Reset" in your UI; you need to wipe app settings but keep WiFi credentials.Clear specific namespace keys.prefs.clear()
You are changing the data schema (e.g., changing a float to an int) and need to wipe the old namespace cleanly.Clear the namespace, then write a version key.prefs.clear() followed by prefs.putUInt("schema_v", 2)
Your device is throwing ESP_ERR_NVS_NO_FREE_PAGES and prefs.begin() is failing.Deep erase the NVS partition to rebuild the page index.nvs_flash_erase_partition("nvs")
You are at the bench, the ESP32 is stuck in a boot loop, and Serial output is garbled.Nuclear wipe of the entire flash chip.Terminal: esptool.py --port COM3 erase_flash

Default Recommendation: If you are building a standard IoT sensor or home automation node, terminate your decision path at prefs.clear(). It is safe, respects other namespaces (like the WiFi stack's "nvs.net80211" namespace), and requires no ESP-IDF C headers.

Extending and Simplifying the Build

How to Extend: Schema Versioning

The biggest mistake makers make with NVS is changing their data structure in code without wiping the old flash data. When the ESP32 boots the new firmware, it reads the old binary blob and misinterprets the bytes, leading to garbage values or crashes.

Extend the build by adding a schema version check in your setup() loop:

uint8_t storedVersion = prefs.getUChar("schema_v", 0);
if (storedVersion < CURRENT_SCHEMA_VERSION) {
  Serial.println("[MIGRATE] Schema outdated. Wiping namespace.");
  prefs.clear();
  prefs.putUChar("schema_v", CURRENT_SCHEMA_VERSION);
}

This ensures that whenever you update your firmware's data structure, the ESP32 automatically deletes the old preferences namespace contents and starts fresh, without requiring manual button presses or serial commands.

How to Simplify: Drop the ESP-IDF Calls

If you are strictly building a hobby project and do not care about the 12-byte overhead of an empty namespace header lingering in the flash dictionary, strip out all #include <nvs_flash.h> references. Rely entirely on the Arduino Preferences.h wrapper. It handles the nvs_commit() calls under the hood, preventing you from accidentally leaving flash transactions open, which is a primary cause of memory leaks in long-running ESP32 deployments.

For deeper architectural details on how Espressif handles flash wear-leveling and page garbage collection, refer to the official Espressif NVS Flash API Documentation. You can also review the source implementation of the wrapper in the Arduino ESP32 Preferences GitHub Repository to see exactly how the C++ class maps to the underlying C structs.