{"record":{"id":"136d820b0a284188","repo":"apache/skywalking","slug":"load-rule-file-failed","errorCode":null,"errorMessage":"Load rule file {} failed","messagePattern":"Load rule file (.+?) failed","errorType":"exception","errorClass":"UnexpectedException","httpStatus":null,"severity":"error","filePath":"oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java","lineNumber":125,"sourceCode":"                }\n                return formedEnabledRules.keySet().stream().anyMatch(rule -> {\n                    boolean matches = FileSystems.getDefault().getPathMatcher(\"glob:\" + rule)\n                        .matches(root.relativize(p));\n                    if (matches) {\n                        formedEnabledRules.put(rule, true);\n                    }\n                    return matches;\n                });\n            }).forEach(p -> {\n                final String rel = root.relativize(p).toString();\n                final String ruleName = rel.substring(0, rel.lastIndexOf('.'));\n                // Keep the actual extension: both .yaml and .yml load, and synthesising .yaml for\n                // a .yml rule points the provenance at a file that does not exist.\n                diskPaths.put(ruleName, rel);\n                try {\n                    diskBytes.put(ruleName, Files.readAllBytes(p));\n                } catch (IOException e) {\n                    throw new UnexpectedException(\"Load rule file \" + p.getFileName() + \" failed\", e);\n                }\n            });\n        }\n\n        if (formedEnabledRules.containsValue(false)) {\n            List<String> rulesNotFound = formedEnabledRules.keySet().stream()\n                    .filter(rule -> !formedEnabledRules.get(rule))\n                    .collect(Collectors.toList());\n            throw new UnexpectedException(\"Some configuration files of enabled rules are not found, enabled rules: \" + rulesNotFound);\n        }\n\n        // Merge with classpath-discovered resolvers (runtime-rule DB, plus any future\n        // priority-ranked source). ACTIVE substitutes existing disk entries; INACTIVE\n        // drops them. Resolver-only rules (no disk twin) are NOT merged here — they're\n        // applied by RuleSync.runOnce post-seal via the dynamic layer channel.\n        final Map<String, byte[]> merged = useInstalledManager\n            ? RuleSetMerger.merge(path, diskBytes)\n            : RuleSetMerger.merge(path, diskBytes, manager);","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java#L107-L143","documentation":"UnexpectedException ('Load rule file X failed') thrown while the Rules loader walks the MAL rules directory and Files.readAllBytes raises an IOException for one rule file. It means the file was visible to the directory walker but could not be read — permissions changed, the file was deleted mid-walk, or the filesystem raised an I/O error.","triggerScenarios":"An IOException during Files.readAllBytes(p) for a rule file under the meter-analyzer rules path (rulesPath config). Typical on containers where the rules directory is bind-mounted read-only with odd permissions, or when a file is removed/truncated between directory listing and read.","commonSituations":"Kubernetes volume mounts with restrictive fileMode; sidecars (config rewriters, secret injectors) atomically replacing rule files while OAP boots; NFS/FUSE-backed mounts returning transient I/O errors; disk-full conditions.","solutions":["Check file permissions: the OAP process user needs read access to every .yaml/.yml under the rules directory","Verify filesystem health and that no process is mutating rule files during OAP startup (stagger config-sync sidecars vs OAP boot)","If the file was intentionally deleted, remove any stale reference to it from the enabled-rules list and restart","Retry OAP startup after fixing the mount/permission; the exception aborts rule loading so a restart is required"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before OAP start: verify readability of every rule file\ntry (Stream<Path> s = Files.walk(rulesPath)) {\n    for (Path p : (Iterable<Path>) s.filter(f -> f.toString().endsWith(\".yaml\") || f.toString().endsWith(\".yml\"))::iterator) {\n        if (!Files.isReadable(p)) throw new IllegalStateException(\"Not readable: \" + p);\n    }\n}","typeGuard":null,"tryCatchPattern":"catch (UnexpectedException e) { /* check e.getCause() instanceof IOException; fix mount/permissions and restart OAP */ }","preventionTips":["Grant the OAP process user read access to the whole rules directory in Docker/K8s manifests","Keep config-sync sidecars from rewriting rule files exactly while OAP boots","Mount rules from a stable ConfigMap/volume, avoid mutating live rule files"],"tags":["mal","io","rule-config","filesystem","startup"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}