apache/skywalking · critical · IllegalStateException
registry_misconfigured
registry_misconfigured
Error message
No DebugRecorderFactory registered for catalog {catalog} — phase 1d wiring incomplete. What it means
Thrown by DebugSessionRegistry.install when a rule's GateHolder resolves on this node but no registered DebugRecorderFactory claims the rule's catalog. Factories are added via registerRecorderFactory() and resolved by iterating a CopyOnWriteArrayList asking each factory to match the RuleKey; an empty or incomplete list means the dsl-debugging module was wired without an engine (LAL/MAL/OAL) recorder provider — the message calls this 'phase 1d wiring incomplete'. This is a module-configuration defect, not a user-input error: it can only happen when the catalog's engine module never registered its factory at boot.
Source
Thrown at oap-server/server-admin/dsl-debugging/src/main/java/org/apache/skywalking/oap/server/admin/dsl/debugging/session/DebugSessionRegistry.java:186
final String clientId, final SessionLimits limits) {
final DebugSession existing = sessions.get(sessionId);
if (existing != null) {
return new InstallOutcome(InstallOutcome.Status.ALREADY_INSTALLED, existing);
}
// Resolve the holder FIRST. The active-session ceiling only applies to nodes
// that actually own the rule — if this node doesn't have the live artifact,
// surfacing TOO_MANY_SESSIONS would falsely reject a session whose actual
// holder lives on a peer with capacity, breaking the LB-safe contract. The
// load-shedding role of the cap is preserved: an attacker spamming installs
// at unloaded rules still gets NOT_LOCAL (the cheap path), and only nodes
// that would actually bind a recorder enforce the cap.
final GateHolder holder = resolveHolder(ruleKey);
if (holder == null) {
return InstallOutcome.NOT_LOCAL_OUTCOME;
}
final DebugRecorderFactory factory = resolveFactory(ruleKey);
if (factory == null) {
throw new IllegalStateException(
"No DebugRecorderFactory registered for catalog " + ruleKey.getCatalog()
+ " — phase 1d wiring incomplete.");
}
final AbstractDebugRecorder recorder = factory.create(sessionId, ruleKey, holder, limits);
final long now = System.currentTimeMillis();
final DebugSession session = new DebugSession(
sessionId, clientId, ruleKey, recorder, holder, now,
now + limits.getRetentionMillis()
);
// Atomic slot reservation + holder bind: cap-check, putIfAbsent, AND
// holder.addRecorder all run under the same lock so a concurrent
// {@link #uninstall} (or reaper-driven stop) cannot remove the session
// BETWEEN registry-publication and holder-binding and leave an
// unreachable recorder bound to the holder. Both install and uninstall
// take the registry lock first, then the holder lock (via add/remove
// recorder which is synchronized on the holder), preserving the same
// lock order in both directions — no deadlock.
final DebugSession reserved;View on GitHub (pinned to 102af09b4a)
Solutions
- Check the module/provider list in application.yml: ensure the module that owns the failing catalog (per the error's catalog name) is enabled, so its provider registers a DebugRecorderFactory at start()
- Verify the factory's supported-catalog/satisfiedBy logic actually returns true for the catalog named in the message — a typo in the catalog string silently never matches
- If this is a custom build, add/restore the registerRecorderFactory(...) call in the owning module's provider start phase and restart the OAP node
- As a workaround only, route debug installs to a node where the factory is registered — but treat the underlying wiring gap as a defect to fix
Example fix
// before (custom provider, recorder never registered)
public void start() {
// ... engine wiring ...
}
// after
public void start() {
// ... engine wiring ...
debugSessionRegistry.registerRecorderFactory(new LalDebugRecorderFactory(...));
} Defensive patterns
Strategy: validation
Validate before calling
final DebugRecorderFactory factory = registry.resolveFactoryFor(ruleKey); // expose or reflect resolveFactory
if (factory == null) {
return error("debug-recorder-factory-missing for catalog " + ruleKey.getCatalog()
+ " — check module wiring before installing sessions");
} Try / catch
catch (IllegalStateException e) when message starts with 'No DebugRecorderFactory registered': treat as permanent config error — fail fast, alert the operator, do NOT retry; check module wiring before the next install attempt.
Prevention
- Boot-time smoke test: after OAP start, verify every loaded catalog has a matching DebugRecorderFactory before opening the debug-session API
- Keep dsl-debugging and the engine modules in one feature set — never enable one without the other in packaging configs
- Add a startup assertion that iterates loaded catalogs and fails module start if resolveFactory returns null
When it happens
Trigger: Calling the debug-session install API (gRPC/REST path into DebugSessionRegistry.install) for a rule in catalog X, on a node where resolveHolder(ruleKey) returns a holder but resolveFactory(ruleKey) returns null — i.e. the rule loaded (holder exists) yet no DebugRecorderFactory.satisfiedBy match exists for that catalog. Typical when a custom OAP packaging starts the dsl-debugging module without the module that registers recorders for that catalog, or when a new catalog was added without a corresponding factory registration.
Common situations: Custom OAP distribution that includes dsl-debugging but drops the module whose provider calls registerRecorderFactory() for the affected catalog; Upgrading to a version where a new rule catalog exists but the recorder factory SPI implementation was not added/registered; Test harnesses that construct DebugSessionRegistry directly and forget to call registerRecorderFactory before install
Related errors
- Duplicate RuleEngine registration for catalog '{catalog}': {
- LogAnalyzerModule Factory unavailable for LAL compile of {so
- MeterSystem unavailable for MAL compile of {sourceName}
- Load meter analyzer configs failed
- Failed to load GenAI configuration file.
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/1c224adf49cc0e95.
Report an issue: GitHub.