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
- Define the reported key in platform.txt/boards.txt or pass it via compiler/recipe extra flags
- Fix the typo in the recipe placeholder so it matches a defined preference
- Upgrade the platform to a version compatible with the IDE's expected variables
- 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
- Verify every {placeholder} in custom recipes exists in preferences
- Compile with verbose output to spot empty substitutions early
- Keep platform.txt recipes in sync with IDE variable names
- Use extra_flags for optional values instead of hard references
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
- throw new PreferencesMapException(k)
- 'Invalid quoting: no closing [' + escapingChar + '] char fou
- KeyError(key)
AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06).
Data as JSON: /api/errors/e60940302df9c690.
Report an issue: GitHub.