arduino/Arduino · error · Exception

'Invalid quoting: no closing [' + escapingChar + '] char fou

Error message

'Invalid quoting: no closing [' + escapingChar + '] char found.'

What it means

StringReplacer.quotedSplit splits a formatted command string into arguments honoring quoting/escaping characters (e.g. quotes around paths with spaces). If the string ends while an escaping/quoting char is still open (no closing quote), it throws Exception("Invalid quoting: no closing [<char>] char found."). This guards against unbalanced quotes in recipes or command templates.

Source

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

        }

        escapingChar = first;
        i = i.substring(1);
        escapedArg = "";
      }

      if (!i.endsWith(escapingChar)) {
        escapedArg += i + " ";
        continue;
      }

      escapedArg += i.substring(0, i.length() - 1);
      if (escapedArg.trim().length() != 0 || acceptEmptyArguments)
        res.add(escapedArg);
      escapingChar = null;
    }
    if (escapingChar != null)
      throw new Exception("Invalid quoting: no closing [" + escapingChar +
          "] char found.");
    return res.toArray(new String[0]);
  }

  public static String replaceFromMapping(String src, Map<String, String> map) {
    return replaceFromMapping(src, map, "{", "}");
  }

  public static String replaceFromMapping(String src, Map<String, String> map,
                                          String leftDelimiter,
                                          String rightDelimiter) {
    for (Map.Entry<String, String> entry : map.entrySet()) {
      String keyword = leftDelimiter + entry.getKey() + rightDelimiter;
      if (entry.getValue() != null && keyword != null) {
          src = src.replace(keyword, entry.getValue());
      }
    }
    return src;

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Open the recipe/template string and balance the quotes around the reported character
  2. Count quote characters in the offending pattern to find the odd one
  3. Escape literal quote characters if they are part of a value rather than delimiters
  4. Reinstall/restore the original platform.txt if the recipe was corrupted by editing

Example fix

// before
recipe.c.combine.pattern="{compiler.c.elf.cmd} {object_files} -o {build.path}/{build.project_name}.elf " // trailing space ate the closing quote intent
// after
recipe.c.combine.pattern="{compiler.c.elf.cmd} {object_files} -o {build.path}/{build.project_name}.elf"
Defensive patterns

Strategy: validation

Validate before calling

int count = 0;
for (char c : pattern.toCharArray()) if (c == '"') count++;
if (count % 2 != 0) throw new IllegalStateException("Unbalanced quotes in: " + pattern);

Try / catch

try {
  String[] args = StringReplacer.formatAndSplit(src, dict);
} catch (Exception e) {
  if (e.getMessage().contains("Invalid quoting"))
    logger.error("Fix quotes in pattern: " + src);
  else throw e;
}

Prevention

When it happens

Trigger: Calling quotedSplit (directly or via formatAndSplit) on a string where a quote/escape character opened but never closed — e.g. a recipe value like ""{compiler.path}gcc -o "{build.path}/out"" missing its final quote, or odd number of escaping chars.

Common situations: Hand-edited platform.txt recipes with unbalanced quotes; paths with quotes stripped or mangled by shell/JSON escaping; copy-paste of recipes losing a trailing quote; values containing unbalanced quote characters in filenames.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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