Skip to content

StackOverflowError (FreeMarker ConcatenatedHash) at theme render time when kcContext contains large lists — kcContextExclusionsFtl block is inlined inside <#list keys as key> loop #1039

Description

@patrick-primesign

Title

StackOverflowError (FreeMarker ConcatenatedHash) at theme render time when kcContext contains large lists — kcContextExclusionsFtl block is inlined inside <#list keys as key> loop

Describe the bug

The generated Keycloakify FTL templates place the entire kcContextExclusionsFtl block (the long series of <@addToXKeycloakifyMessagesIfMessageKey str="..." /> calls, from str="environment" through str="federatedIdentityUnmatchedEssentialClaimMessage") inside the per-key serialization loop:

<#list keys as key>
    ...
    <@addToXKeycloakifyMessagesIfMessageKey str="environment" />
    <@addToXKeycloakifyMessagesIfMessageKey str="anotherKey" />
    ...
    <@addToXKeycloakifyMessagesIfMessageKey str="federatedIdentityUnmatchedEssentialClaimMessage" />
</#list>

Because that block does not depend on key, it is re-evaluated on every iteration. Each iteration adds another layer to FreeMarker's internal ConcatenatedHash structure. When kcContext contains a large list (in our case ~50 documents to sign, which expands the number of keys/iterations significantly), FreeMarker recurses through the resulting ConcatenatedHash chain and hits a StackOverflowError while rendering the page.

The block should be emitted once, outside the loop — for example immediately after <@addNonAutomaticallyGatherableMessagesToXKeycloakifyMessages />.

To Reproduce

  1. Build a Keycloakify theme (any recent version that emits kcContextExclusionsFtl inline in the loop).
  2. Deploy it to Keycloak.
  3. Trigger a login flow where kcContext contains a large list (e.g. ~50+ items — in our case a list of documents to sign passed via a required action / custom page).
  4. Load the page.

Expected: the page renders normally.
Actual: Keycloak returns HTTP 500; server log shows a FreeMarker StackOverflowError with a deep stack whose repeated frames go through freemarker.ext.beans.ConcatenatedHash (or ConcatenatedHashEx) .get(...) / .keys(...).

Environment

  • Keycloakify version: 11.15.10
  • Keycloak version: 26.5.7
  • JDK: 21

This Merge Request, was made with AI help.

Note: We created a patch-script that runs after the keycloakify build to fix this in the generated files, via line moving.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions