Bug Description
openclaw backup create fails with ENOENT when a session file is cleaned up (deleted by the gateway's session compaction/cleanup process) between when the backup command enumerates all session files and when it tries to archive them.
Exact Error
Error: ENOENT: no such file or directory, lstat '\"/path/to/.openclaw/agents/main/sessions/28cd361b-3f8f-4852-8a31-f7ffc31ede55.jsonl\"\
Process exited with code 1
Steps to Reproduce
- Run the OpenClaw gateway with active sessions
- Trigger
openclaw backup create (e.g., via cron job)
- While
backup create is enumerating session files in agents/<agent>/sessions/, the gateway's session compaction or cleanup process deletes one or more of those session .jsonl files
- When
backup create later tries to lstat the now-deleted session file, it throws ENOENT and the entire backup fails
Environment
- OpenClaw Version: 2026.4.14 (commit 323493f)
- OS: Linux (any)
- Trigger: Concurrent session compaction/cleanup running alongside
backup create
Root Cause
This is a race condition: the backup command scans for all session files first, then attempts to archive them. If the gateway's compaction process (which runs periodically or on schedule) deletes session files between the scan phase and the archive phase, the backup fails entirely.
The existing session compaction behavior is tracked in issue #15404 (closed, but the underlying behavior may still cause this race).
Expected Behavior
The backup command should gracefully skip session files that no longer exist rather than failing the entire backup.
Proposed Fix
Before adding each session file to the tar archive, check whether it still exists on disk. If it was cleaned up by compaction, skip it with a warning and continue. The backup should succeed with a note in the output that N session files were skipped due to concurrent cleanup.
A simple pattern for the fix in the session-archiving loop:
for (const sessionFile of sessionFiles) {
try {
await stat(sessionFilePath)
} catch (e: unknown) {
if (isENOENT(e)) {
logWarning(\`Skipping session \${sessionFile}: file no longer exists (cleaned up by compaction)\`)
continue
}
throw e
}
// proceed to archive
}
This mirrors how the codebase already handles ENOENT in comparable situations (e.g., fileHistory.ts uses the same pattern for deleted tracked files).
Workaround
Use --only-config to bypass session archiving entirely, but this loses session history in the backup.
Impact
- Severity: Medium — backup fails entirely due to a transient, expected condition (session cleanup)
- Users running
backup create on a schedule while the gateway is running will experience intermittent backup failures
- No data is lost, but the backup artifact is not produced
Bug Description
openclaw backup createfails with ENOENT when a session file is cleaned up (deleted by the gateway's session compaction/cleanup process) between when the backup command enumerates all session files and when it tries to archive them.Exact Error
Steps to Reproduce
openclaw backup create(e.g., via cron job)backup createis enumerating session files inagents/<agent>/sessions/, the gateway's session compaction or cleanup process deletes one or more of those session.jsonlfilesbackup createlater tries tolstatthe now-deleted session file, it throws ENOENT and the entire backup failsEnvironment
backup createRoot Cause
This is a race condition: the backup command scans for all session files first, then attempts to archive them. If the gateway's compaction process (which runs periodically or on schedule) deletes session files between the scan phase and the archive phase, the backup fails entirely.
The existing session compaction behavior is tracked in issue #15404 (closed, but the underlying behavior may still cause this race).
Expected Behavior
The backup command should gracefully skip session files that no longer exist rather than failing the entire backup.
Proposed Fix
Before adding each session file to the tar archive, check whether it still exists on disk. If it was cleaned up by compaction, skip it with a warning and continue. The backup should succeed with a note in the output that N session files were skipped due to concurrent cleanup.
A simple pattern for the fix in the session-archiving loop:
This mirrors how the codebase already handles ENOENT in comparable situations (e.g.,
fileHistory.tsuses the same pattern for deleted tracked files).Workaround
Use
--only-configto bypass session archiving entirely, but this loses session history in the backup.Impact
backup createon a schedule while the gateway is running will experience intermittent backup failures