openclaw - ✅(Solved) Fix [Bug]: backup create packages manifest.json twice when TMPDIR points to ~/.openclaw/tmp [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#75007Fetched 2026-05-01 05:39:07
View on GitHub
Comments
1
Participants
2
Timeline
17
Reactions
2
Author
Timeline (top)
referenced ×7mentioned ×4subscribed ×4commented ×1

When the macOS LaunchAgent environment sets TMPDIR to ~/.openclaw/tmp (as OpenClaw does to solve SQLite temp file issues), openclaw backup create produces an archive containing two identical copies of manifest.json.

Root Cause

backup-create.ts line 351 uses os.tmpdir() to create the temp directory:

const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-"));

When os.tmpdir() returns ~/.openclaw/tmp, tar recursively packs the entire ~/.openclaw payload, including the temp dir containing manifest.json. Since manifest.json is also passed explicitly to tar as the first archive entry, the result is two identical manifest.json entries in the final archive.

Fix Action

Fixed

PR fix notes

PR #75031: fix(backup): use resolvePreferredOpenClawTmpDir for temp archive dir (#75007)

Description (problem / solution / changelog)

Problem

Fixes #75007.

When the macOS LaunchAgent sets TMPDIR=~/.openclaw/tmp (which OpenClaw does to solve SQLite temp file issues), backup create called os.tmpdir() to create its working temp directory. This placed the temp dir inside the state directory payload, causing tar to pack manifest.json twice:

  1. Once as an explicit first entry (correct)
  2. Once recursively when tar packs the state dir and walks into the tmp subdir

Result: the final archive contains two identical manifest.json entries.

Fix

Replace the os.tmpdir() call in createBackupArchive with resolvePreferredOpenClawTmpDir(), which already exists in infra/tmp-openclaw-dir.ts and is used across the codebase (helpers, monitor, status.gather, restart). It always returns a path outside the state payload (/tmp/openclaw on POSIX, or a user-scoped fallback), ignoring the TMPDIR environment variable.

Remove the now-unused os import.

Test

Added regression test: set TMPDIR to point inside the test state dir (the bug scenario), create a backup, verify the archive contains exactly one manifest.json entry.

All 6 backup-create.test.ts tests pass.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/infra/backup-create.test.ts (modified, +79/-1)
  • src/infra/backup-create.ts (modified, +23/-2)

Code Example

const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-"));

---

// Current (buggy)
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-"));

// Suggested fix
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
const tempDir = await fs.mkdtemp(path.join(resolvePreferredOpenClawTmpDir(), "openclaw-backup-"));
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug

Summary

When the macOS LaunchAgent environment sets TMPDIR to ~/.openclaw/tmp (as OpenClaw does to solve SQLite temp file issues), openclaw backup create produces an archive containing two identical copies of manifest.json.

Root cause

backup-create.ts line 351 uses os.tmpdir() to create the temp directory:

const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-"));

When os.tmpdir() returns ~/.openclaw/tmp, tar recursively packs the entire ~/.openclaw payload, including the temp dir containing manifest.json. Since manifest.json is also passed explicitly to tar as the first archive entry, the result is two identical manifest.json entries in the final archive.

Steps to reproduce

  1. Start OpenClaw gateway via macOS LaunchAgent (the launchd plist sets TMPDIR=~/.openclaw/tmp by design)
  2. Run openclaw backup create
  3. Check the archive: tar -tvf <backup> | grep manifest shows two entries with identical content

Actual impact

  • Backup functionality works and backup verify passes
  • The archive contains one extra manifest.json entry of identical content
  • Violates the design principle that temp files should never be inside the payload being archived

Suggested fix

backup-create.ts should call the already-existing resolvePreferredOpenClawTmpDir() utility (from tmp-openclaw-dir.ts) instead of using os.tmpdir() directly:

// Current (buggy)
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-"));

// Suggested fix
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
const tempDir = await fs.mkdtemp(path.join(resolvePreferredOpenClawTmpDir(), "openclaw-backup-"));

Note: resolvePreferredOpenClawTmpDir() is already used across multiple OpenClaw modules (e.g. helpers, monitor, status.gather, restart) and returns a safe tmp path outside the payload.

Environment

  • OpenClaw: 2026.4.26
  • OS: macOS (via LaunchAgent)
  • Install: npm global

extent analysis

TL;DR

Use the resolvePreferredOpenClawTmpDir() utility to determine the temporary directory instead of relying on os.tmpdir() to avoid including temporary files in the backup archive.

Guidance

  • Replace the line const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-")); in backup-create.ts with the suggested fix to use resolvePreferredOpenClawTmpDir().
  • Verify the change by running openclaw backup create and checking the archive contents with tar -tvf <backup> | grep manifest to ensure only one manifest.json entry is present.
  • Review other parts of the codebase that use os.tmpdir() to ensure they also use the preferred temporary directory utility if necessary.

Example

import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
const tempDir = await fs.mkdtemp(path.join(resolvePreferredOpenClawTmpDir(), "openclaw-backup-"));

Notes

This fix assumes that resolvePreferredOpenClawTmpDir() correctly returns a temporary directory outside the payload being archived, as stated in the issue.

Recommendation

Apply the workaround by using resolvePreferredOpenClawTmpDir() to determine the temporary directory, as it ensures that temporary files are not included in the backup archive, aligning with the design principle.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: backup create packages manifest.json twice when TMPDIR points to ~/.openclaw/tmp [1 pull requests, 1 comments, 2 participants]