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:
- Basis-Modul existiert: Der Chunk
subagent-registry-CflSFWBm.jswird korrekt generiert und im dist-Ordner abgelegt. - Interner Import-Fehler: Innerhalb von
subagent-registry-CflSFWBm.jsreferenziert ein interner dynamischer Importsubagent-registry.runtime.jsunter 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));
- 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 queued → running → completed 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 dasexports-Feld inpackage.jsonfalsch konfiguriert ist.
Kontekst: Kann auftreten, wenn subagent-registry auch über Package-Exports referenziert wird.- Stilles Task-Queue-Hängen
Aufgaben verbleiben imqueued-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))"