arduino/Arduino · error · PreferencesMapException

throw new PreferencesMapException(key)

Error message

throw new PreferencesMapException(key)

What it means

StringReplacer.checkIfRequiredKeyIsMissingOrExcept verifies that after substituting all known {key} placeholders from the dictionary, no unresolved tag remains in the string. If a placeholder cannot be resolved, it throws PreferencesMapException(key) signalling that a required build property is missing from preferences. This enforces that recipes like compiler recipes have all their required variables defined.

Source

Thrown at arduino-core/src/processing/app/helpers/StringReplacer.java:67

      break;
    }

    // Inject tag inside the dictionary
    dict.put(key, tag);

    // Recursive replace with a max depth of 10 levels.
    String res;
    for (int i = 0; i < 10; i++) {
      // Do a replace with dictionary
      res = StringReplacer.replaceFromMapping(src, dict);
      if (res.equals(src))
        break;
      src = res;
    }

    // If the resulting string contains the tag, then the key is required
    if (src.contains(tag)) {
      throw new PreferencesMapException(key);
    }
  }

  public static String[] formatAndSplit(String src, Map<String, String> dict) throws Exception {
    String res;

    // Recursive replace with a max depth of 10 levels.
    for (int i = 0; i < 10; i++) {
      // Do a replace with dictionary
      res = StringReplacer.replaceFromMapping(src, dict);
      if (res.equals(src))
        break;
      src = res;
    }

    // Split the resulting string in arguments
    return quotedSplit(src, "\"'", false);
  }

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Define the reported key in platform.txt/boards.txt or pass it via compiler/recipe extra flags
  2. Fix the typo in the recipe placeholder so it matches a defined preference
  3. Upgrade the platform to a version compatible with the IDE's expected variables
  4. Temporarily echo the recipe with all variables to see which value is empty (verbose compile)

Example fix

// before
recipe.c.o.pattern="{compiler.gcc.path}{compiler.gcc.cmd} ... {compiler.some.undefined.flag}" // throws
// after: define it or make it optional
recipe.c.o.pattern="{compiler.gcc.path}{compiler.gcc.cmd} ... {compiler.c.extra_flags}"
compiler.c.extra_flags=""
Defensive patterns

Strategy: validation

Validate before calling

Set<String> keys = collectPlaceholders(recipePattern); // regex \{([^}]+)\}
for (String k : keys)
  if (prefs.get(k) == null)
    throw new IllegalStateException("Recipe references undefined key: " + k);

Try / catch

try {
  StringReplacer.checkIfRequiredKeyIsMissingOrExcept(pattern, dict, tag);
} catch (PreferencesMapException e) {
  logger.error("Recipe variable undefined: " + e.getMessage());
}

Prevention

When it happens

Trigger: Formatting a build recipe/pattern (via StringReplacer/PReferencesMap-based substitution) where a {placeholder} in the recipe string has no corresponding key in the supplied preferences map — e.g. recipe.c.o.pattern referencing {compiler.c.extra_flags} that is undefined.

Common situations: Custom or third-party platform.txt recipes referencing variables never defined; typo'd key in a recipe; removed/renamed preference in a newer IDE used by an old platform definition; user-overridden build.path/runtime vars deleted in platform.local.txt.

Related errors


AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06). Data as JSON: /api/errors/e60940302df9c690. Report an issue: GitHub.