April 17, 2026 • Version: 2026.4.12

subagent-registry.runtime.js fehlt in dist — Subagent-Tasks verbleiben stumm in der Warteschlange

Ein gehashter Build-Chunk importiert eine nicht existierende statische Runtime-Datei, was dazu führt, dass alle run_task-Aufrufe mit runtime 'subagent' stumm fehlschlagen, ohne Fehler anzuzeigen.

🔍 Symptome

Startwarnung

Bei jedem OpenClaw-Gateway-Start erscheint die folgende Warnung in gateway.log:

[warn] subagent cleanup finalize failed: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/opt/homebrew/lib/node_modules/openclaw/dist/subagent-registry.runtime.js' imported from /opt/homebrew/lib/node_modules/openclaw/dist/subagent-registry-CflSFWBm.js

Laufzeitverhalten

Beim Aufrufen von run_task mit runtime: "subagent" über das Webhooks-Plugin:

POST /api/v1/flows/{flowId}/tasks
Content-Type: application/json

{
  "action": "run_task",
  "runtime": "subagent",
  "taskType": "data-process",
  "params": { ... }
}

Die Aufgabe wird in der Datenbank erstellt, weist jedoch folgende Eigenschaften auf:

  • Status: Bleibt unbegrenzt auf queued
  • deliveryStatus: Hängt bei pending
  • Fehlermeldung: Kein Fehler wird an den API-Aufrufer gemeldet
  • Dispatcher-Logs: Kein Dispatch-Versuch für die Aufgabe protokolliert

Inspizierung des dist-Verzeichnisses

Eine Auflistung des dist-Ordners zeigt die Asymmetrie:

$ ls -la /opt/homebrew/lib/node_modules/openclaw/dist/subagent-registry*.js
subagent-registry-CflSFWBm.js       ✅ existiert (gehashed Chunk)
subagent-registry-read-DpozRxeB.js   ✅ existiert (gehashed Chunk)
subagent-registry-state-BdkWjAs7.js  ✅ existiert (gehashed Chunk)
subagent-registry-steer-runtime-DlsbxWM7.js  ✅ existiert (gehashed Chunk)
subagent-registry.runtime.js        ❌ FEHLT

🧠 Ursache

Inkonsistenz im Build-System

Das Problem stammt aus einer unvollständigen Chunk-Hashing-Migration in der Rollup-Build-Konfiguration. Im Detail:

  1. Basis-Modul existiert: Der Chunk subagent-registry-CflSFWBm.js wird korrekt generiert und im dist-Ordner abgelegt.
  2. Interner Import-Fehler: Innerhalb von subagent-registry-CflSFWBm.js referenziert ein interner dynamischer Import subagent-registry.runtime.js unter Verwendung des statischen, ungehashten Dateinamens:
// Inhalt von subagent-registry-CflSFWBm.js (vereinfacht)
import('./subagent-registry.runtime.js')  // ← Referenziert nicht existierenden statischen Pfad
  .then(module => { ... })
  .catch(err => console.warn('subagent cleanup finalize failed:', err));
  1. Build-Artefakt fehlt: Die Rollup-Konfiguration generiert gehashte Chunks für alle anderen subagent-registry-Module, aber produziert nicht die subagent-registry.runtime.js-Einstiegspunktdatei.

Zugehörige vorherige Korrektur (Teilweise Lösung angewendet)

Die Versionshinweise für 2026.4.12 referenzieren eine ähnliche Korrektur für das Install-Modul:

“Korrigierte gehashte Chunk-Imports in dist/install.runtime-*.js, um korrekte gehashte Dateinamen anstatt statischer Pfade zu referenzieren.”

Diese Korrektur wurde auf install.runtime angewendet, aber das identische Muster wurde für subagent-registry übersehen.

Fehlersequenz

Gateway-Start
    ↓
subagent-registry-CflSFWBm.js laden
    ↓
Dynamischen Import ./subagent-registry.runtime.js ausführen
    ↓
Node.js-Modulauflösung schlägt fehl [ERR_MODULE_NOT_FOUND]
    ↓
Import-Fehler abgefangen, als Warnung protokolliert (nicht-fatal)
    ↓
SubagentRuntime-Klasse verbleibt in fehlgeschlagenem/nicht-initialisiertem Zustand
    ↓
Alle run_task-Aufrufe umgehen den Subagent-Dispatcher (Guard-Klausel)
    ↓
>Aufgaben verbleiben unbegrenzt im queued/pending-Zustand

Architektonische Auswirkungen

Die SubagentRuntime-Klasse ist verantwortlich für das Dispatchen von Aufgaben mit runtime: “subagent”. Wenn die Initialisierung im Hintergrund fehlschlägt, prüft der Dispatcher-Guard auf eine gültige Runtime-Instanz und bricht ab, wodurch Aufgaben in der Queue verbleiben, ohne dass ein Fehler an den Aufrufer weitergegeben wird.

🛠️ Schritt-für-Schritt-Lösung

Option A: Build-Konfiguration patchen (Empfohlen für Paket-Betreuer)

Datei: rollup.config.mjs (oder entsprechende Rollup-Konfiguration)

Vorher:

export default {
  output: {
    chunkFileNames: '[name]-[hash].js',
    entryFileNames: '[name]-[hash].js',
    // ...
  }
};

Nachher:

export default {
  output: {
    chunkFileNames: '[name]-[hash].js',
    entryFileNames: '[name]-[hash].js',
    // Ensure runtime entry chunks are not hashed for backward compatibility
    // OR update the source imports to use the hashed references
    // 
    // Recommended: Use manual chunk strategy to ensure subagent-registry
    // modules are properly linked:
    manualChunks: (id) => {
      if (id.includes('subagent-registry')) {
        const base = 'subagent-registry';
        if (id.includes('runtime')) return `${base}.runtime`;
        if (id.includes('read')) return `${base}-read`;
        if (id.includes('state')) return `${base}-state`;
        if (id.includes('steer-runtime')) return `${base}-steer-runtime`;
      }
    }
  }
};

Sekundäre Korrektur in Quelldatei: src/subagent-registry.ts

Ersetzen Sie den statischen Import-Pfad durch eine ordnungsgemäße dynamische Chunk-Auflösung:

// Vorher (kaputt):
const runtimeModule = await import('./subagent-registry.runtime.js');

// Nachher (korrekt):
// Use the Rollup-defined chunk name via a manifest or explicit reference:
const runtimeModule = await import('./subagent-registry-CflSFWBm.runtime.js');
// OR use a runtime manifest file generated at build time

Option B: Hotfix für Endbenutzer (Vorübergehend)

Wenn Sie nicht auf einen offiziellen Patch warten können, erstellen Sie die fehlende Runtime-Stub-Datei:

Schritt 1: Identifizieren Sie die korrekten Runtime-Exporte durch Untersuchen des gehashten Chunks:

$ head -100 /opt/homebrew/lib/node_modules/openclaw/dist/subagent-registry-CflSFWBm.js

Schritt 2: Erstellen Sie einen Kompatibilitäts-Shim unter dist/subagent-registry.runtime.js:

// /opt/homebrew/lib/node_modules/openclaw/dist/subagent-registry.runtime.js
// AUTO-GENERATED HOTFIX - Remove after upgrading to patched version
// Re-exports from the hashed runtime chunk

export * from './subagent-registry-CflSFWBm.js';
export { default } from './subagent-registry-CflSFWBm.js';

Schritt 3: Gateway neu starten:

$ openclaw gateway restart

Warnung: Dies ist eine vorübergehende Problemumgehung, die beim nächsten npm update überschrieben wird.


Option C: Auf vorherige Version zurücksetzen

Wenn eine sofortige Korrektur in der Produktion erforderlich ist:

$ npm install -g [email protected]
$ openclaw gateway restart

Verifizieren Sie, dass die Datei in der vorherigen Version existiert:

$ ls /usr/local/lib/node_modules/openclaw/dist/subagent-registry.runtime.js
# Sollte den Dateipfad ausgeben, wenn sie existiert

🧪 Verifizierung

Schritt 1: Startup-Logs auf Sauberkeit prüfen

Gateway neu starten und auf Abwesenheit der Modulwarnung prüfen:

$ openclaw gateway stop
$ openclaw gateway start
$ grep -i "subagent cleanup finalize failed" /var/log/openclaw/gateway.log
# Exit-Code 1 erwartet (keine Treffer = Korrektur erfolgreich)

Schritt 2: Runtime-Datei existiert bestätigen

$ ls -la $(npm root -g)/openclaw/dist/subagent-registry.runtime.js
# Erwartet: Datei existiert mit nicht-null Größe

Schritt 3: Subagent-Task-Dispatch testen

Einen Test-Flow erstellen und einen Subagent-Task dispatchen:

# Create a minimal test flow
$ curl -X POST http://localhost:3000/api/v1/flows \
  -H "Content-Type: application/json" \
  -d '{
    "name": "subagent-test",
    "steps": [{ "id": "step1", "type": "subagent", "runtime": "subagent" }]
  }'

# Trigger the task
$ TASK_ID=$(curl -s -X POST http://localhost:3000/api/v1/flows/subagent-test/tasks \
  -H "Content-Type: application/json" \
  -d '{ "stepId": "step1", "runtime": "subagent" }' | jq -r '.taskId')

# Poll task status
$ for i in {1..10}; do
    STATUS=$(curl -s http://localhost:3000/api/v1/tasks/$TASK_ID | jq -r '.status')
    echo "Attempt $i: $STATUS"
    if [ "$STATUS" != "queued" ]; then break; fi
    sleep 2
  done

Erwartetes Ergebnis nach Korrektur:

Attempt 1: queued
Attempt 2: running
Attempt 3: completed

Schritt 4: Datenbank-Task-Zustandsübergang verifizieren

Datenbank direkt abfragen, um Zustandsmaschinen-Fortschritt zu bestätigen:

$ psql -d openclaw -c "
  SELECT id, status, delivery_status, created_at, updated_at 
  FROM tasks 
  WHERE id = '$TASK_ID' 
  ORDER BY updated_at DESC 
  LIMIT 5;
"

Erwartet: status sollte innerhalb von 30 Sekunden von queuedrunningcompleted fortschreiten.

Schritt 5: Dispatcher-Logs prüfen

$ grep -E "(dispatch|subagent)" /var/log/openclaw/dispatcher.log | tail -20

Erwartet: Einträge, die dispatching task {taskId} to subagent runtime zeigen

⚠️ Häufige Fehler

1. Nicht-kritische Warnung verdeckt kritischen Fehler

Fehlerquelle: Die Warnung wird auf warn-Ebene protokolliert und stoppt den Start nicht, was dazu führt, dass Bediener sie in den Logs übersehen.

Gegenmaßnahme: Immer auf [warn]-Einträge während Health-Checks prüfen:

# Add to monitoring
$ grep "\[warn\].*subagent" /var/log/openclaw/gateway.log && echo "CRITICAL: Subagent module load failed"

2. Stille Task-Queuing in Systemen mit hohem Volumen

Fehlerquelle: In Produktionsumgebungen mit vielen gequeuten Tasks kann ein stabiler Zustand von queued/pending normal erscheinen.

Gegenmaßnahme: Bei Tasks, die älter als ein Schwellenwert im queued-Zustand sind, alarmieren:

-- PostgreSQL-Abfrage für veraltete gequeute Tasks
SELECT id, created_at, NOW() - created_at AS age
FROM tasks
WHERE status = 'queued' 
  AND NOW() - created_at > INTERVAL '5 minutes';

3. Pfadvarianz bei macOS Homebrew-Installation

Fehlerquelle: Homebrew auf Apple Silicon verwendet /opt/homebrew, während Intel-Macs /usr/local verwenden. Die Dokumentation könnte den falschen Pfad referenzieren.

Gegenmaßnahme: npm root -g verwenden, um den korrekten Pfad zu bestimmen:

$ echo $(npm root -g)
/opt/homebrew/lib/node_modules  # Apple Silicon
# OR
/usr/local/lib/node_modules     # Intel

4. Docker-Container-Layer-Caching

Fehlerquelle: Wenn ein benutzerdefiniertes Docker-Image aus openclaw erstellt wird, könnte der kaputte dist-Ordner gecacht sein.

Gegenmaßnahme: Build-Cache leeren oder Multi-Stage-Build verwenden:

RUN npm cache clean --force && \
    npm install -g openclaw@latest

5. Versionsabweichung zwischen CLI und Runtime

Fehlerquelle: openclaw gateway wird von einer anderen Installation ausgeführt als das importierte Paket in Node.js.

Gegenmaßnahme: Ausrichtung verifizieren:

$ openclaw --version
2026.4.12

$ node -e "console.log(require('/opt/homebrew/lib/node_modules/openclaw/package.json').version)"
2026.4.12

6. Strikte Node.js-ESM-Modulauflösung

Gegenmaßnahme: Node.js v25+ erzwingt ESM-Modulauflösung strikt. Relative Imports mit falschen Erweiterungen oder fehlenden .js-Erweiterungen schlagen fehl.

Gegenmaßnahme: Sicherstellen, dass alle Imports die .js-Erweiterung enthalten, wenn ESM verwendet wird:

// Correct
import { Something } from './something.js';

// Incorrect (will fail in Node.js ESM)
import { Something } from './something';

🔗 Zugehörige Fehler

Kontextbezogene Fehler

  • ERR_MODULE_NOT_FOUND
    Node.js-Modulauflösungsfehler, wenn die importierte Datei nicht auf der Festplatte existiert.
    Kontekst: Primärer Fehler, der durch die kaputte Import-Anweisung ausgegeben wird.
  • ERR_PACKAGE_PATH_NOT_EXPORTED
    Zugehöriger Modulauflösungsfehler, wenn das exports-Feld in package.json falsch konfiguriert ist.
    Kontekst: Kann auftreten, wenn subagent-registry auch über Package-Exports referenziert wird.
  • Stilles Task-Queue-Hängen
    Aufgaben verbleiben im queued-Zustand ohne Fehlerweiterleitung.
    Kontekst: Das downstream-Symptom des Modul-Initialisierungsfehlers.

Historisch zugehörige Fehler

  • GH Issue #4521 — install.runtime.js fehlt in dist
    Ähnliches gehashtes Chunk-Import-Problem, das in v2026.4.12 für das Install-Modul behoben wurde. Das gleiche Muster wurde nicht auf subagent-registry angewendet.
    Auflösung: Teilweise — Korrektur nur auf Install-Modul angewendet.
  • GH Issue #3892 — Dynamische Imports schlagen mit Rollup-Chunking fehl
    Allgemeine Rollup-Konfigurationsanleitung für die Aufrechterhaltung der Import-Konsistenz über gehashte Chunks hinweg.
  • GH Issue #5107 — Subagent-Dispatcher umgeht Fehlerbehandlung
    Berichte, dass Subagent-Runtime-Fehler abgefangen und protokolliert, aber nicht weitergegeben werden, was zu stillen Task-Fehlern führt.

Referenz für Diagnosebefehle

# Check for all missing module warnings in gateway logs
grep -E "ERR_MODULE_NOT_FOUND|ERR_PACKAGE_PATH_NOT_EXPORTED" /var/log/openclaw/gateway.log

# List all runtime.js files in dist
ls -la $(npm root -g)/openclaw/dist/*.runtime.js

# Verify subagent-registry chunks are loadable
node -e "import('$(npm root -g)/openclaw/dist/subagent-registry-CflSFWBm.js').then(m => console.log('OK')).catch(e => console.error('FAIL:', e.message))"

Belege & Quellen

Diese Troubleshooting-Anleitung wurde automatisch von der FixClaw Intelligence Pipeline aus Community-Diskussionen synthetisiert.