fix(velocity): fail loud when global macro library load fails (#35601)#35768
Merged
Conversation
8 tasks
Contributor
|
Claude finished @dsolistorres's task in 2m 39s —— View job dotCMS Backend Review
✅ dotCMS Backend Review: no issues found. |
Contributor
|
✅ dotCMS Backend Review: no issues found. |
2 tasks
dsilvam
approved these changes
May 20, 2026
wezell
requested changes
May 20, 2026
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - Switch the fail-on-missing flag from a Velocity runtime property (rsvc.getBoolean / system.properties) to a dotCMS feature flag read via Config.getBooleanProperty("VELOCITY_LIBRARY_FAIL_ON_MISSING"). - Default to false to preserve historical behavior. Existing customers with optional/missing macro libraries continue to start normally; operators opt in once they have verified their library files load cleanly. Removes the now-unused RuntimeConstants.VM_LIBRARY_FAIL_ON_MISSING and the corresponding system.properties entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - Switch the fail-on-missing flag from a Velocity runtime property (rsvc.getBoolean / system.properties) to a dotCMS feature flag read via Config.getBooleanProperty("VELOCITY_LIBRARY_FAIL_ON_MISSING"). - Default to false to preserve historical behavior. Existing customers with optional/missing macro libraries continue to start normally; operators opt in once they have verified their library files load cleanly. Removes the now-unused RuntimeConstants.VM_LIBRARY_FAIL_ON_MISSING and the corresponding system.properties entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0e8d688 to
941c881
Compare
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - VelocimacroFactory: pass `this` to Logger.error in the ResourceNotFoundException catch, matching the adjacent catch block and the repo-wide convention. - VelocimacroFactoryTest: assert `verify(rsvc).getTemplate(MISSING_LIBRARY)` on the no-throw paths so a future refactor that short-circuits the load loop can't silently pass these tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - Switch the fail-on-missing flag from a Velocity runtime property (rsvc.getBoolean / system.properties) to a dotCMS feature flag read via Config.getBooleanProperty("VELOCITY_LIBRARY_FAIL_ON_MISSING"). - Default to false to preserve historical behavior. Existing customers with optional/missing macro libraries continue to start normally; operators opt in once they have verified their library files load cleanly. Removes the now-unused RuntimeConstants.VM_LIBRARY_FAIL_ON_MISSING and the corresponding system.properties entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - VelocimacroFactory: pass `this` to Logger.error in the ResourceNotFoundException catch, matching the adjacent catch block and the repo-wide convention. - VelocimacroFactoryTest: assert `verify(rsvc).getTemplate(MISSING_LIBRARY)` on the no-throw paths so a future refactor that short-circuits the load loop can't silently pass these tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6d64f8e to
f93ef0e
Compare
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - Switch the fail-on-missing flag from a Velocity runtime property (rsvc.getBoolean / system.properties) to a dotCMS feature flag read via Config.getBooleanProperty("VELOCITY_LIBRARY_FAIL_ON_MISSING"). - Default to false to preserve historical behavior. Existing customers with optional/missing macro libraries continue to start normally; operators opt in once they have verified their library files load cleanly. Removes the now-unused RuntimeConstants.VM_LIBRARY_FAIL_ON_MISSING and the corresponding system.properties entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f93ef0e to
a6f4529
Compare
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
Addresses PR #35768 review feedback: - VelocimacroFactory: pass `this` to Logger.error in the ResourceNotFoundException catch, matching the adjacent catch block and the repo-wide convention. - VelocimacroFactoryTest: assert `verify(rsvc).getTemplate(MISSING_LIBRARY)` on the no-throw paths so a future refactor that short-circuits the load loop can't silently pass these tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f93ef0e to
a6f4529
Compare
dsolistorres
added a commit
that referenced
this pull request
May 21, 2026
…test (#35601) Addresses PR #35768 review feedback: - Add a comment at the throw site noting that this exception is terminal: the factory ends in a partial state (permission setup, namespace usage, and autoreload never run) and MUST be discarded. Documents the current contract so a future caller does not catch VelocityException and try to reuse the instance. - Add an assertion in initThrowsWhenFlagIsTrue that the exception message contains FLAG_KEY, pinning the actionable opt-out hint so a future refactor cannot silently drop it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
VelocimacroFactory silently swallowed ResourceNotFoundException when loading velocimacro.library files at engine init, allowing init to "succeed" with no global macros registered. After K8s pod restarts with transient I/O errors (notably on EFS-backed volumes), #renderMarks and #editContentlet rendered as literal text on every page until the JVM was restarted. The catch now logs the failed library name at ERROR and tracks failures so init can throw VelocityException when any required library failed. A new flag velocimacro.library.fail-on-missing (default true) lets self-hosted operators preserve the legacy silent-warn behavior if they intentionally configure optional libraries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses PR #35768 review feedback: - Switch the fail-on-missing flag from a Velocity runtime property (rsvc.getBoolean / system.properties) to a dotCMS feature flag read via Config.getBooleanProperty("VELOCITY_LIBRARY_FAIL_ON_MISSING"). - Default to false to preserve historical behavior. Existing customers with optional/missing macro libraries continue to start normally; operators opt in once they have verified their library files load cleanly. Removes the now-unused RuntimeConstants.VM_LIBRARY_FAIL_ON_MISSING and the corresponding system.properties entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses PR #35768 review feedback: - VelocimacroFactory: pass `this` to Logger.error in the ResourceNotFoundException catch, matching the adjacent catch block and the repo-wide convention. - VelocimacroFactoryTest: assert `verify(rsvc).getTemplate(MISSING_LIBRARY)` on the no-throw paths so a future refactor that short-circuits the load loop can't silently pass these tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…test (#35601) Addresses PR #35768 review feedback: - Add a comment at the throw site noting that this exception is terminal: the factory ends in a partial state (permission setup, namespace usage, and autoreload never run) and MUST be discarded. Documents the current contract so a future caller does not catch VelocityException and try to reuse the instance. - Add an assertion in initThrowsWhenFlagIsTrue that the exception message contains FLAG_KEY, pinning the actionable opt-out hint so a future refactor cannot silently drop it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f18be4b to
a0f36b7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #35601 (follow-up implementation from spike #35329).
VelocimacroFactorysilently swallowedResourceNotFoundExceptionwhen loading the configuredvelocimacro.libraryfiles at engine init, allowingengine.init()to return successfully with no global macros registered. After K8s pod restarts with transient I/O errors (notably on EFS-backed volumes),#renderMarks($element)and#editContentletrendered as literal text on every public page until the JVM was restarted.Changes
VelocimacroFactory.initVelocimacro()— track loaded/failed libraries through the load loop. TheResourceNotFoundExceptioncatch now logs atERRORwith the failed library file name. After the loop, anINFOsummary line lists loaded and failed libraries (greppable for ops). When any library failed, throwVelocityExceptionwith an actionable message naming the failed library and the opt-out flag.velocimacro.library.fail-on-missing(defaulttrue) preserves the legacy silent-warn behavior for self-hosted operators who intentionally configure optional libraries.RuntimeConstants.VM_LIBRARY_FAIL_ON_MISSING— new constant.system.properties— explicit default with a one-line comment.VelocimacroFactoryTest(new) — three unit tests coveringfail-on-missing=true,fail-on-missing=false, and the default.Why this is enough
engine.init()throws →VelocityUtil.getEngine()(VelocityUtil.java:65) rethrows asDotRuntimeException→ propagates out ofInitServlet.init()at line 199 →dotcms.started.upis never set → existingServletContainerHealthCheckalready gates/readyzon that flag → K8s readiness probe fails → no traffic routed → eventual pod restart gives EFS time to settle.Companion ticket #35602 (
VelocityHealthCheck) is still valuable as defense-in-depth — it catches the opt-out case (fail-on-missing=false) and any future post-init macro corruption that this flag wouldn't see.Test plan
VelocimacroFactoryTest— 3/3 pass (fail-on-missing=truethrows,falsesucceeds, default throws). Runtime ERROR/INFO log lines verified in test output.VelocityUtilTest— 20/20 pass (no regression).bogus-smoke-test.vmtovelocimacro.library, ranjust dev-run. Observed:ERROR runtime.VelocimacroFactory - Velocimacro : VM library not found : bogus-smoke-test.vm : ...INFO runtime.VelocimacroFactory - Velocimacro libraries loaded: [VM_global_library.vm, dotCMS_library.vm, dotCMS_library_ext.vm] ; failed: [bogus-smoke-test.vm]VelocityException: Velocimacro : required VM libraries failed to load: [bogus-smoke-test.vm]. Set velocimacro.library.fail-on-missing=false to allow startup with missing libraries.InitServlet.init(InitServlet.java:199)and rethrow asDotRuntimeExceptionInitServlet init Completedabsent from log (init aborted beforedotcms.started.up=true)/dotmgt/readyzreturns HTTP 503/dotmgt/livezreturns HTTP 503🤖 Generated with Claude Code
This PR fixes: #35601