OpenAPITools/openapi-generator · error · IllegalArgumentException

cacheScope key cannot be empty

Error message

cacheScope key cannot be empty

What it means

CacheLambda (the 'cache' mustache lambda used by C# generators) splits its body at the first '|' or line break; the part before it, trimmed, becomes the cache key. If that key part is empty — the body starts with '|' or the first line is blank/whitespace — an IllegalArgumentException is thrown because a recall later could never address the stored content. Like the missing-separator error, this fires at template render time.

Source

Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/mustache/CacheLambda.java:63

    public void execute(Fragment fragment, Writer writer) throws IOException {
        String content = fragment.execute();

        // Accept either "key|content" or a multiline form where the first line is the key.
        int separatorIndex = content.indexOf('|');
        if (separatorIndex < 0) {
            int lineBreakIndex = findFirstLineBreakIndex(content);
            if (lineBreakIndex >= 0) {
                separatorIndex = lineBreakIndex;
            }
        }

        if (separatorIndex < 0) {
            throw new IllegalArgumentException("cacheScope requires 'key|content' or 'key\\ncontent'");
        }

        String key = content.substring(0, separatorIndex).trim();
        if (key.isEmpty()) {
            throw new IllegalArgumentException("cacheScope key cannot be empty");
        }

        int contentStartIndex = separatorIndex + 1;
        // For CRLF, skip both '\r' and '\n'. For LF-only/CR-only, skip just one character.
        if (separatorIndex < content.length() && content.charAt(separatorIndex) == '\r') {
            if (contentStartIndex < content.length() && content.charAt(contentStartIndex) == '\n') {
                contentStartIndex++;
            }
        }

        this.cacheContent.contentByKey.put(key, content.substring(contentStartIndex));
    }

    private int findFirstLineBreakIndex(String content) {
        // Keep this simple and cross-platform by checking all common line endings.
        int unix = content.indexOf('\n');
        int windows = content.indexOf('\r');

View on GitHub (pinned to fcec517be3)

Solutions

  1. Put a non-empty key before the separator: {{#cache}}userModel|...content...{{/cache}}.
  2. If using the multiline form, make the first line the key and start content on line two.
  3. Lint cached blocks for a non-blank prefix before the first '|' or newline.

Example fix

{{! before }}
{{#cache}}|public partial class UserModel { }{{/cache}}

{{! after }}
{{#cache}}userModel|public partial class UserModel { }{{/cache}}
Defensive patterns

Strategy: validation

Validate before calling

# lint: reject cache blocks whose key part (before '|' or newline) is empty/whitespace
grep -rnE '\{\{#cache\}\}(\||[[:space:]]*(\||$))' templates/ && {
  echo "ERROR: {{#cache}} key cannot be empty" >&2; exit 1;
}

Prevention

When it happens

Trigger: A template block {{#cache}}|some content{{/cache}} (leading pipe), or a multiline body whose first line is only spaces, e.g. {{#cache}}\n content{{/cache}} — the trimmed key is empty.

Common situations: Reformatting mustache templates with auto-indent that pushes the key onto its own blank line; copying a cached block and deleting its key but leaving the separator; template snippets from PRs where the key placeholder was never filled in.

Related errors


AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22). Data as JSON: /api/errors/3a0eef1036078fdc. Report an issue: GitHub.