{"record":{"id":"946599ea3ab096fe","repo":"redisson/redisson","slug":"unable-to-locate-redisson-instance-by-name-jndi-946599","errorCode":null,"errorMessage":"Unable to locate Redisson instance by name: ${jndiName}","messagePattern":"Unable to locate Redisson instance by name: (.+?)","errorType":"exception","errorClass":"CacheException","httpStatus":null,"severity":"error","filePath":"redisson-hibernate/redisson-hibernate-4/src/main/java/org/redisson/hibernate/JndiRedissonRegionNativeFactory.java","lineNumber":53,"sourceCode":"\n    private static final long serialVersionUID = -4814502675083325567L;\n\n    public static final String JNDI_NAME = CONFIG_PREFIX + \"jndi_name\";\n    \n    @Override\n    protected RedissonClient createRedissonClient(Properties properties) {\n        String jndiName = ConfigurationHelper.getString(JNDI_NAME, properties);\n        if (jndiName == null) {\n            throw new CacheException(JNDI_NAME + \" property not set\");\n        }\n        \n        Properties jndiProperties = JndiServiceImpl.extractJndiProperties(properties);\n        InitialContext context = null;\n        try {\n            context = new InitialContext(jndiProperties);\n            return (RedissonClient) context.lookup(jndiName);\n        } catch (NamingException e) {\n            throw new CacheException(\"Unable to locate Redisson instance by name: \" + jndiName, e);\n        } finally {\n            if (context != null) {\n                try {\n                    context.close();\n                } catch (NamingException e) {\n                    throw new CacheException(\"Unable to close JNDI context\", e);\n                }\n            }\n        }\n    }\n\n    @Override\n    public void stop() {\n    }\n\n}\n","sourceCodeStart":35,"sourceCodeEnd":70,"githubUrl":"https://github.com/redisson/redisson/blob/91188987c2a9023e7fedabff758681ad9b107f25/redisson-hibernate/redisson-hibernate-4/src/main/java/org/redisson/hibernate/JndiRedissonRegionNativeFactory.java#L35-L70","documentation":"RedissonConnection.scan() iterates master entries directly over raw connections, producing a live Cursor. Cursors require request/response round-trips per batch, so Redisson refuses to run SCAN while the connection is in MULTI queueing or pipeline mode, throwing UnsupportedOperationException from doScan.","triggerScenarios":"Calling conn.scan(ScanOptions) inside RedisTemplate.executePipelined(...) or inside a multi()/exec() SessionCallback. The ScanCursor is lazily evaluated, so the exception surfaces when the cursor is first advanced or closed (inside the pipeline callback), not when scan() is called.","commonSituations":"Wrapping RedisTemplate.scan(cursor) in executePipelined hoping to batch results; calling scan within RedisTransactionalSessionCallback; frameworks that implicitly pipeline callbacks (e.g. some RedisTemplate operations inside executePipelined).","solutions":["Run scan outside any pipeline/transaction: use RedisTemplate.scan(options) or a raw connection cursor on a non-pipelined connection.","Collect keys with SCAN first, then pipeline the follow-up operations on those keys.","If a single blocking call is acceptable in pipeline mode, use conn.keys(pattern) instead of scan."],"exampleFix":"// before\nredisTemplate.executePipelined((RedisCallback<Object>) conn -> {\n    Cursor<byte[]> c = conn.scan(ScanOptions.scanOptions().match(\"sess:*\").build());\n    c.forEachRemaining(k -> redisTemplate.delete(new String(k))); // throws inside pipeline\n    return null;\n});\n\n// after\ntry (Cursor<byte[]> c = redisTemplate.scan(ScanOptions.scanOptions().match(\"sess:*\").build())) {\n    List<String> keys = c.stream().map(String::new).collect(Collectors.toList());\n    if (!keys.isEmpty()) redisTemplate.delete(keys);\n}","handlingStrategy":"validation","validationCode":"if (conn.isPipelined() || conn.isQueueing()) {\n    throw new IllegalStateException(\"SCAN not allowed here; collect keys first, pipeline later\");\n}\ntry (Cursor<byte[]> c = conn.scan(options)) { ... }","typeGuard":null,"tryCatchPattern":"catch (UnsupportedOperationException e) where message contains \"pipeline / transaction mode\": move the scan to a fresh connection obtained outside executePipelined and re-run.","preventionTips":["Standardize on RedisTemplate.scan(options) for key iteration and reserve executePipelined for sets of known keys.","Never create cursors inside RedisCallback/SessionCallback bodies that run pipelined.","Integration-test batch jobs in both plain and pipelined modes so pipeline/scan mixing is caught early."],"tags":["redis","redisson","scan","pipeline","transaction","cursor"],"backgroundTag":null,"analyzedSha":"91188987c2a9023e7fedabff758681ad9b107f25","analyzedAt":"2026-08-14T11:39:42.619Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}