{"record":{"id":"c2bec266ef72113c","repo":"apache/skywalking","slug":"mal-register-failed-for-sourcename-partial","errorCode":null,"errorMessage":"MAL register failed for {sourceName} (partial)","messagePattern":"MAL register failed for (.+?) \\(partial\\)","errorType":"http","errorClass":"ApplyException","httpStatus":500,"severity":"error","filePath":"oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/apply/MalFileApplier.java","lineNumber":163,"sourceCode":"            ? sourceName.substring(firstSlash + 1)\n            : sourceName;\n        final RuleClassLoader ruleLoader = DSLClassLoaderManager.INSTANCE.newBuilder(\n            catalog, ruleName, kind, contentHash);\n        final ClassPool pool = new ClassPool(ClassPool.getDefault());\n        pool.appendClassPath(new LoaderClassPath(ruleLoader));\n\n        final MetricConvert convert;\n        try {\n            convert = new MetricConvert(rule, meterSystem, pool, ruleLoader, storageOpt);\n        } catch (final MetricConvert.PartialRegistrationException pre) {\n            // Phase-2 register threw partway. Carry ONLY the subset that actually landed in\n            // MeterSystem — the caller uses this set for rollback. Passing the full enumerated\n            // set here would remove metrics the old bundle still owns (disastrous on\n            // FILTER_ONLY edits, where by definition every metric name is also in the old\n            // bundle). The layer-registry changes are reverted now so a failed MeterSystem\n            // register does not leak a half-applied layer state.\n            layerRegistry.rollback(appliedClaims);\n            throw new ApplyException(\n                \"MAL register failed for \" + sourceName + \" (partial)\",\n                pre.getCause() == null ? pre : pre.getCause(),\n                pre.getRegisteredBeforeFailure());\n        } catch (final Throwable t) {\n            // Phase-1 compile failure or other pre-register throw. Nothing was registered with\n            // MeterSystem, so rollback set is empty — passing a non-empty set would cause the\n            // caller to unregister metrics the old bundle owns and this apply never touched.\n            layerRegistry.rollback(appliedClaims);\n            throw new ApplyException(\"MAL compile failed for \" + sourceName, t, Collections.emptySet());\n        }\n        // All DDL for this file's metrics is now fired. If the opt deferred its schema fence\n        // (batched apply via withSchemaChangeDeferredFence), run the single barrier here so the\n        // whole file waits ONCE instead of one fence per metric/downsampling. A fence timeout is\n        // a non-fatal WARN inside the closure; only a barrier transport error throws, which\n        // aborts this apply exactly as an inline per-resource fence would have.\n        //\n        // EXCEPTION: when fenceRunByCaller is set (the runtime-rule REST apply), the orchestrator\n        // runs the fence itself AFTER the durable commit + peer resume, on a background thread, so","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/apply/MalFileApplier.java#L145-L181","documentation":"ApplyException thrown by MalFileApplier.apply when MetricConvert construction throws PartialRegistrationException — phase-2 MeterSystem registration got partway through the file's metrics before failing. Crucially, the exception carries ONLY the metric subset that actually landed (pre.getRegisteredBeforeFailure()), never the fully enumerated set: on FILTER_ONLY edits every metric name also exists in the old bundle, so over-broad rollback would delete metrics the still-serving old rule owns. Layer-registry claims are rolled back immediately before throwing.","triggerScenarios":"Applying a MAL file where one metric registers into MeterSystem but a later one fails — duplicate metric name already in MeterSystem, a metric definition rejected by storage DDL, or an expression compiling to an invalid metric type mid-registration.","commonSituations":"A hot-updated MAL file introduces a metric name that another MAL bundle (often an otel-rules file) already registered; Transient storage unavailability while opening streams during registration; Metric name collisions after renaming a rule but keeping the old file installed in parallel","solutions":["Check the cause for the failing metric name; if it collides, rename the metric in the new file or remove the old bundle that owns it","Verify cluster-wide that no peer concurrently registered the same metric names (rollouts racing)","Retry the apply after storage is healthy if the cause was a storage DDL/stream failure — the applier already rolled back layer claims, and the returned partial set lets the orchestrator unregister only what landed","Audit for stale bundles: list registered meters and remove orphaned files before re-apply"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight: ensure no metric name in the new file is already registered elsewhere\nSet<String> existing = meterSystemHasTheseNames(newFileMetricNames(prefix, rules));\nif (!Collections.disjoint(existing, incomingNames)) reject(\"metric name collision: \" + overlap);","typeGuard":null,"tryCatchPattern":"catch (MalFileApplier.ApplyException e) when 'MAL register failed ... (partial)': unregister EXACTLY e.getPartiallyRegistered() (the subset that landed), then resolve the colliding/failed metric from the cause and re-apply. Never roll back more than the partial set — the old bundle still owns the rest.","preventionTips":["Reserve metric prefixes per team/bundle to prevent cross-file name collisions","List installed meters before applying a renamed or duplicated bundle","Treat the partial set in the exception as authoritative for cleanup — it is deliberately the landed subset, not the enumeration"],"tags":["mal","registration","partial-failure","runtime-rule"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}