Redis extension on Lucee 7 fails to resolve due to a Bundle-SymbolicName mismatch in the AWS Secrets Manager dependency. We manually patched the jar, cleared the OSGi cache, and restarted, but the error persists. Direct classloading bypasses OSGi and works, but causes side effects on unrelated CFCs. Looking for guidance on whether we’re missing a step or this is a known issue.
First of all: yes, I know this is long. ![]()
But this report is the result of roughly three fairly intense days of debugging, during which we went from “Redis doesn’t work” to inspecting OSGi manifests, patching jars by hand, clearing Felix caches, bypassing OSGi entirely and eventually breaking something completely unrelated.
So I thought it was worth documenting the whole journey, including the dead ends.
One thing feels very strange to me: I assume redis.extension is fairly widely used, so I would expect a problem this fundamental to have surfaced much more often.
That makes me suspect I may still be missing something obvious somewhere - but after three days of testing different versions, JVMs, manifests, bundle names, caches and workarounds, I genuinely can’t find a way out of this.
So if there is something stupidly simple I’m overlooking, I will be very happy to be embarrassed by the answer. ![]()
Environment
-
Lucee:
7.0.5-SNAPSHOT+41 -
CommandBox:
6.3.4+00883 -
Java:
11.0.29(Ubuntu build, Eclipse Adoptium-equivalent) -
Also reproduced identically on OpenJDK 21, Lucee 7’s recommended target, so the JVM version does not appear to be a factor.
-
OS: Ubuntu, CommandBox-managed Runwar/Undertow
-
redis.extensionversions tested:3.0.1.0— javax, expected to fail on Jakarta4.0.0.24.1.0.0-SNAPSHOT
All three eventually fail on the same missing OSGi dependency.
The error
org.osgi.framework.BundleException: Unable to resolve redis.extension [N](R N.0): missing
requirement [redis.extension [N](R N.0)] osgi.wiring.bundle;
(&(osgi.wiring.bundle=org.lucee.aws-java-sdk-secretsmanager-all)(bundle-version>=1.12.758)(!(bundle-version>=2.0.0)))
Unresolved requirements: [[redis.extension [N](R N.0)] osgi.wiring.bundle;
(&(osgi.wiring.bundle=org.lucee.aws-java-sdk-secretsmanager-all)(bundle-version>=1.12.758)(!(bundle-version>=2.0.0)))]
On OpenJDK 21, Lucee also logs this more explicit message:
Lucee was not able to download/load the following bundles [org.lucee.aws-java-sdk-secretsmanager-all:1.12.758;]
The failure appears the first time the application actually touches the named cache — for example with cachePut(), cacheGet() or cacheClear() — using a cache connection backed by redis.extension.
Example:
// Application.cfc
this.cache.connections["RedisCache"] = {
class: "lucee.extension.io.cache.redis.simple.RedisCache",
bundleName: "redis.extension",
bundleVersion: "4.1.0.0-SNAPSHOT",
storage: false,
custom: [ /* host/port/password/... */ ],
default: "object"
};
this.cache.object = "RedisCache";
First clue: Lucee downloads a dependency under a different symbolic name
Lucee correctly identifies the missing dependency and tries to fetch it:
"bundle-download","Could not find [/bundles/org.lucee.aws-java-sdk-secretsmanager-all-1.12.758.jar] in lucee.jar"
"bundle-download","Downloading bundle [org.lucee.aws-java-sdk-secretsmanager-all:1.12.758] from
https://repo1.maven.org/maven2/org/lucee/awssecretsmanager/1.12.758/awssecretsmanager-1.12.758.jar
and copying to .../WEB-INF/lucee-server/bundles/org.lucee.aws-java-sdk-secretsmanager-all-1.12.758.jar"
The download itself succeeds: a valid jar of roughly 341 KB appears in WEB-INF/lucee-server/bundles/.
But the bundle actually ends up as:
org.lucee.aws-secretsmanager-1.12.758.jar
while Redis requires:
org.lucee.aws-java-sdk-secretsmanager-all-1.12.758.jar
We manually renamed the jar and restarted Lucee.
Lucee simply downloaded it again and recreated the shorter-named bundle on the next resolution attempt.
At this stage, this strongly suggested that the issue was not the filesystem filename itself, but the bundle identity declared inside the jar.
That suspicion was later confirmed directly by inspecting the manifest.
Confirmed: the published jar has a different Bundle-SymbolicName
We extracted the downloaded jar and inspected:
META-INF/MANIFEST.MF
The relevant values are:
Bundle-Name: org.lucee.aws-secretsmanager
Bundle-SymbolicName: org.lucee.aws-secretsmanager
Bundle-Version: 1.12.758
But redis.extension requires:
org.lucee.aws-java-sdk-secretsmanager-all
So the version is correct, but the symbolic name is not the one required by Redis.
We also checked the other bundles referenced by this jar:
org.lucee.aws-java-sdk-core
org.lucee.aws-jmespath-java
Both are already present and expose the expected Bundle-SymbolicName.
The Secrets Manager bundle is the only mismatch we found.
We patched the manifest by hand
Because apparently debugging Redis had not become strange enough yet, we patched the jar ourselves.
We changed:
Bundle-Name: org.lucee.aws-secretsmanager
Bundle-SymbolicName: org.lucee.aws-secretsmanager
to:
Bundle-Name: org.lucee.aws-java-sdk-secretsmanager-all
Bundle-SymbolicName: org.lucee.aws-java-sdk-secretsmanager-all
A small side adventure: the manifest uses CRLF line endings, so our first sed command with a $ end-of-line anchor did not match. cat -A eventually revealed the friendly little ^M.
We then:
-
Repackaged the jar with
jar cfm. -
Saved it as:
org.lucee.aws-java-sdk-secretsmanager-all-1.12.758.jar -
Verified the actual resulting jar again using:
unzip -p ... | grep Bundle- -
Confirmed that the symbolic name and version were now exactly what Redis requires.
-
Cleared Lucee’s separate OSGi
felix-cache. -
Performed a full server stop/start.
The OSGi bundle ID assigned to redis.extension changed from [73] to [52], confirming that this was a genuinely fresh registration rather than an old cached resolution attempt.
And then…
exactly the same error.
BundleException: Unable to resolve redis.extension ...
missing requirement org.lucee.aws-java-sdk-secretsmanager-all
So at this point we had:
- the exact expected filename;
- the exact expected
Bundle-SymbolicName; - the correct
Bundle-Version; - a freshly rebuilt jar;
- a cleared Felix cache;
- a full server restart;
…and Lucee still refused to resolve it.
That was the point where we stopped blaming the filename. ![]()
Possible second issue: bundles may not simply be discovered from the bundles directory
This result suggests that:
WEB-INF/lucee-server/bundles/
is probably not simply scanned for arbitrary valid OSGi bundles at startup.
There may be some additional internal registry/index/install state that determines which bundles Lucee considers installed and loadable.
This would also fit another thing we observed: the S3 Resource Extension appeared in the Lucee Administrator as “not loaded” despite its files being present.
If such a registry exists, simply dropping a perfectly valid jar into bundles/ may not be sufficient.
We could not take this part much further without knowing more about Lucee’s internal extension/bundle installation machinery.
Side note: 4.1.0.0 exists as a Git tag but is not installable
The lucee/extension-redis repository has a 4.1.0.0 Git tag dated 2026-05-24.
Naturally, we assumed that dropping -SNAPSHOT and using:
bundleVersion: "4.1.0.0"
might be worth trying.
It fails immediately:
org.osgi.framework.BundleException: The OSGi Bundle with name [redis.extension] in version [4.1.0.0]
is not available locally [...bundles] or from the update provider [https://update.lucee.org].
So as far as we can tell, 4.1.0.0 is a source tag but was never published as an installable binary through Lucee’s extension provider.
4.1.0.0-SNAPSHOT is currently the installable 4.1 version.
This seems worth mentioning because it looks like the 4.x publish/release path may have more than one gap.
Side note: org.lucee:redis-extension does not appear to exist on Maven Central
Lucee’s documentation uses this as an example for LUCEE_EXTENSIONS / -Dlucee.extensions:
org.lucee:redis-extension:3.0.0.56
We checked Maven Central directly for:
g:org.lucee AND a:redis-extension
and found no matching artifact.
The only Redis-related artifact under org.lucee we found there was launchdarkly-redis, which is unrelated.
So Redis appears to be distributed through Lucee’s own extension infrastructure rather than Maven Central, despite the Maven-style syntax used in that documentation example.
Confirmed: 1.12.758 is already the newest available Secrets Manager bundle
We also checked whether a later AWS Secrets Manager wrapper might satisfy Redis’s required range:
>= 1.12.758
< 2.0.0
Available org.lucee:awssecretsmanager versions include:
1.12.758
1.12.455
1.12.454
1.11.877.0002L
1.11.877.0001L
1.11.877.0000L
1.11.877
So 1.12.758 is already the newest available version.
There is no later artifact in the required range to try instead.
The S3-extension workaround did not work for us
We found an older Lucee forum thread where someone reported that installing the AWS S3 extension first allowed the Redis extension to resolve afterward.
The theory is plausible: the S3 extension may install another correctly wrapped copy of the AWS SDK dependency Redis needs.
We tried it.
- Installed S3 Resource Extension 2.0.3.1 through Lucee Server Administrator.
- It appeared in the bundle list as “not loaded”.
- Lucee offered an update to
2.1.0.4-beta. - Attempting the update failed silently in the Admin UI.
- The installed version remained
2.0.3.1.
So unfortunately we could not reproduce the workaround reliably in this Lucee 7 environment.
There are also separate reports of S3 extension installation problems on Lucee 7, so this may simply be another manifestation of the same broader extension-resolution problem.
The nuclear option: bypass OSGi completely
After enough time spent trying to make OSGi happy, we asked a slightly different question:
Does the Redis extension’s actual Java code work?
Surprisingly — or perhaps unsurprisingly by this point — yes.
The implementation class is:
lucee.extension.io.cache.redis.simple.RedisCache
and the runtime functionality we use only appears to need org.mongodb.bson for object serialization/deserialization.
So we loaded the jars directly:
this.javaSettings = {
LoadPaths = [ "/libs/redis-extension" ],
loadCFMLClassPath = true,
reloadOnChange = false
};
redisCache = createObject(
"java",
"lucee.extension.io.cache.redis.simple.RedisCache"
).init();
redisCache.init({
host: "...",
port: "...",
password: "..."
});
redisCache.put(
"key",
"value",
javaCast("long", 30000),
javaCast("long", 30000)
);
redisCache.getValue("key");
And this works.
We tested:
initputgetValuecontainsremove
against a real Redis instance.
All worked correctly.
No AWS SDK involved.
No OSGi.
No Server Administrator.
For approximately twenty glorious minutes, we thought we had won.
Unfortunately, direct classloading appears unsafe in our application
Once we wired that implementation into our application’s cache manager — which is used on essentially every request — we started seeing an apparently unrelated error elsewhere:
java.lang.NullPointerException
Cannot invoke "lucee.runtime.component.ComponentPageRef.get(lucee.runtime.PageContext)"
because "this.cpRef" is null
This came from GetMetadata() on perfectly ordinary CFC bean instances inside an unrelated bean-to-JSON utility.
The important observations were:
-
the error appeared repeatedly after introducing the direct Java classloading workaround;
-
it affected unrelated CFC code;
-
a full server restart did not fix it while the workaround remained active;
-
replacing the custom Redis implementation with Lucee’s built-in
lucee.runtime.cache.ram.RamCachemade the problem disappear completely.
The direct Redis object was created once and cached for the application’s lifetime, so this does not appear to be caused by repeatedly creating classloaders.
We did not investigate this enough to call it a Lucee bug with confidence.
Our current suspicion is that:
createObject("java", className, jarPaths)
with explicit jars may share more classloading machinery with Lucee than we expected, and loading the Redis extension this way may interfere with Lucee’s own component class resolution.
But that is currently an inference, not something we have proven.
It probably deserves a separate bug report.
I’m mentioning it here only because it means the direct-classloading approach, although technically able to talk to Redis, does not look like a safe production workaround for us.
We reverted to Lucee’s built-in RAM cache and marked Redis as “do not use in production” in our internal documentation until this is understood.
Questions for the Lucee team
-
Is
org.lucee:awssecretsmanager:1.12.758expected to satisfy theorg.lucee.aws-java-sdk-secretsmanager-allrequirement?
If so, we may be looking at a mismatch between the published bundle metadata and whatredis.extensionexpects. -
Is the AWS Secrets Manager dependency expected to be mandatory even when no Secrets Manager configuration is used?
We may be misunderstanding how that dependency is intended to work, especially because an older thread suggested it had previously been made optional. -
Is there a known-good way to install or obtain the required Secrets Manager bundle on Lucee 7/Jakarta?
-
Are bundles placed manually in
WEB-INF/lucee-server/bundles/expected to be discovered automatically, or is there additional registration/install state involved?
Our patched bundle was still not resolved after clearing the Felix cache and restarting, so we may be missing a required installation step.
Separate classloading question
This may deserve another thread, but since we encountered it while looking for a workaround:
Is:
createObject("java", className, jarPaths)
supposed to use an isolated classloader?
If so, the ComponentPageRef.cpRef NullPointerException we observed after loading the Redis jars may be worth reporting separately.
We do not have enough knowledge of Lucee’s internal classloader hierarchy to determine whether this is a Lucee isolation issue or something caused by our approach, so I don’t want to overstate that conclusion.
Happy to provide more
We can provide, if useful:
- complete startup logs;
- the relevant
Application.cfccache configuration; - the original and patched AWS Secrets Manager jars/manifests;
- a small self-contained
redis-classload-test.cfmreproduction script.
And apologies again for the wall of text. ![]()
After three days of chasing this through Redis, OSGi, AWS jars, manifests, Felix caches and classloaders, the short version stopped being particularly short.
Happy summer Luceers!