{"record":{"id":"e79ffb5083a40001","repo":"juicedata/juicefs","slug":"rangerpermissionchecker-for-volume-volname","errorCode":null,"errorMessage":"RangerPermissionChecker for volume: \" + volName + \" is already created, but no running instance found.","messagePattern":"RangerPermissionChecker for volume: \" \\+ volName \\+ \" is already created, but no running instance found\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"sdk/java/src/main/java/io/juicefs/permission/RangerPermissionChecker.java","lineNumber":83,"sourceCode":"\n  public RangerPermissionChecker(FileSystem superGroupFileSystem, RangerConfig config) {\n    this.superGroupFileSystem = superGroupFileSystem;\n    rangerPlugin = new RangerJfsPlugin(superGroupFileSystem, config.getServiceName(), config.getRangerRestUrl(), config.getPollIntervalMs());\n    rangerPlugin.getConfig().set(\"ranger.plugin.hdfs.service.name\", config.getServiceName());\n    rangerPlugin.getConfig().set(\"ranger.plugin.hdfs.policy.rest.url\", config.getRangerRestUrl());\n    // for test use\n    if (config.getImpl() != null) {\n      rangerPlugin.getConfig().set(\"ranger.plugin.hdfs.policy.source.impl\", config.getImpl());\n    }\n    rangerPlugin.getConfig().setIsFallbackSupported(true);\n    rangerPlugin.init();\n  }\n\n  public static RangerPermissionChecker acquire(String volName, long handle, FileSystem superGroupFileSystem, RangerConfig config) throws IOException {\n    synchronized (runningInstance) {\n      if (!runningInstance.containsKey(volName)) {\n        if (pcs.containsKey(volName)) {\n          throw new IOException(\"RangerPermissionChecker for volume: \" + volName + \" is already created, but no running instance found.\");\n        }\n        RangerPermissionChecker pc = new RangerPermissionChecker(superGroupFileSystem, config);\n        pcs.put(volName, pc);\n        Set<Long> handles = new HashSet<>();\n        handles.add(handle);\n        runningInstance.put(volName, handles);\n        return pc;\n      } else {\n        RangerPermissionChecker pc = pcs.get(volName);\n        if (pc == null) {\n          throw new IOException(\"RangerPermissionChecker for volume: \" + volName + \" is already created, but no instance found.\");\n        }\n        runningInstance.get(volName).add(handle);\n        return pc;\n      }\n    }\n  }\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/permission/RangerPermissionChecker.java#L65-L101","documentation":"RangerPermissionChecker.acquire enforces that at most one permission checker exists per volume. If a checker was previously created (present in pcs) but no running instance is registered in runningInstance (e.g. a previous release() path failed or state was corrupted), acquire throws this IOException instead of creating a duplicate.","triggerScenarios":"Calling RangerPermissionChecker.acquire for a volName that exists in pcs but not in runningInstance — i.e. an earlier acquire created the checker, all handles were removed but pcs entry was never cleaned, or internal state desynchronized between the two maps.","commonSituations":"A release() path threw before removing the pcs entry; multiple FileSystem clients in one JVM across restart cycles; concurrent lifecycle bugs leaving pcs populated while runningInstance is empty.","solutions":["Ensure release() is called for every handle acquired so pcs/runningInstance stay in sync","Restart the client JVM process to clear stale static state","Inspect release logic for exceptions that skip pcs.remove(volName)","Guard against re-acquiring after all handles released until the cleanup path is fixed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"boolean checkerStale(String vol) {\n  // via reflection over internal state, or track client-side usage\n  return acquiredVolumes.getOrDefault(vol, 0) == 0;\n}","tryCatchPattern":"try {\n  pc = RangerPermissionChecker.acquire(volName, handle, fs, config);\n} catch (IOException e) {\n  if (e.getMessage().contains(\"is already created, but no running instance found\")) {\n    LOG.error(\"Stale checker state; restart client JVM and ensure release() is always called\", e);\n  } else throw e;\n}","preventionTips":["Always call release() in a finally block for every acquired handle","Do not manipulate checker lifecycle maps concurrently","Restart the client if acquire/release paths ever throw"],"tags":["ranger","permission","lifecycle","state"],"backgroundTag":"internal-invariant-violation","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}