openclaw - ✅(Solved) Fix [Bug]: LaunchAgent plist env vars still redacted on v2026.3.13 — confirmed reproduction, wrapper workaround included [2 pull requests, 2 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#52771Fetched 2026-04-08 01:19:40
View on GitHub
Comments
2
Participants
2
Timeline
11
Reactions
0
Author
Timeline (top)
commented ×2cross-referenced ×2labeled ×2subscribed ×2

Relates to: #13340 (locked), PR: #26567

Reopening per the bot's instruction on #13340: "If you are absolutely sure it still happens on the latest release, open a new issue with fresh repro steps."

openclaw gateway install --force does not write API keys into the LaunchAgent plist on v2026.3.13, causing all providers to return HTTP 401 after any reboot or gateway restart.

Root Cause

Even when ~/.openclaw/.env is populated with valid keys, the gateway does not use them after a clean launchd start. OpenClaw's loadDotEnv initialises with override: false, meaning environment variables already present in the process environment (injected by launchd from the plist) take precedence over .env values. Since the plist has no API keys, the gateway starts with empty credentials. .env cannot fill the gap because override: false prevents it from overwriting the (absent but already-evaluated) environment.

Fix Action

Fix / Workaround

During testing, openclaw update changed the gateway entry point from index.js to entry.js in /opt/homebrew/lib/node_modules/openclaw/dist/. Any hardcoded path in a post-install patch script breaks silently on update.

Workaround that survives openclaw update (verified)

Step 1: Create the wrapper script

cat > ~/openclaw-gateway-wrapper.sh << 'EOF'
#!/bin/bash
# Workaround for openclaw/openclaw#13340
set -a
source "$HOME/.openclaw/.env"
set +a

PR fix notes

PR #2: fix: load ~/.openclaw/.env for LaunchAgent environment variables (fixes #52771)

Description (problem / solution / changelog)

When installing the Gateway as a LaunchAgent on macOS, environment variables from ~/.openclaw/.env were not being included in the plist's EnvironmentVariables section. This caused API keys and other custom environment variables to be missing after reboot, resulting in HTTP 401 errors.

This fix explicitly loads the .env file during the gateway install process and merges its variables into the service environment with the correct precedence:

  1. .env file variables (lowest priority)
  2. Config env vars from openclaw.json
  3. Internal OPENCLAW_* variables (highest priority)

Fixes #52771

Changed files

  • .agent/workflows/update_clawdbot.md (modified, +7/-7)
  • .agents/skills/openclaw-ghsa-maintainer/SKILL.md (added, +87/-0)
  • .agents/skills/openclaw-parallels-smoke/SKILL.md (added, +77/-0)
  • .agents/skills/openclaw-pr-maintainer/SKILL.md (added, +75/-0)
  • .agents/skills/openclaw-release-maintainer/SKILL.md (added, +225/-0)
  • .agents/skills/openclaw-test-heap-leaks/SKILL.md (added, +71/-0)
  • .agents/skills/openclaw-test-heap-leaks/agents/openai.yaml (added, +4/-0)
  • .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs (added, +265/-0)
  • .agents/skills/parallels-discord-roundtrip/SKILL.md (added, +62/-0)
  • .agents/skills/security-triage/SKILL.md (added, +108/-0)
  • .dockerignore (modified, +6/-0)
  • .github/CODEOWNERS (added, +54/-0)
  • .github/FUNDING.yml (removed, +0/-1)
  • .github/ISSUE_TEMPLATE/bug_report.yml (modified, +21/-25)
  • .github/actions/ensure-base-commit/action.yml (modified, +6/-2)
  • .github/actions/setup-node-env/action.yml (modified, +10/-6)
  • .github/actions/setup-pnpm-store-cache/action.yml (modified, +11/-9)
  • .github/labeler.yml (modified, +91/-14)
  • .github/pull_request_template.md (modified, +27/-1)
  • .github/workflows/auto-response.yml (modified, +43/-5)
  • .github/workflows/ci-bun.yml (added, +72/-0)
  • .github/workflows/ci.yml (modified, +488/-361)
  • .github/workflows/codeql.yml (modified, +8/-5)
  • .github/workflows/docker-release.yml (modified, +123/-40)
  • .github/workflows/install-smoke.yml (modified, +106/-27)
  • .github/workflows/labeler.yml (modified, +16/-13)
  • .github/workflows/macos-release.yml (added, +86/-0)
  • .github/workflows/openclaw-npm-release.yml (added, +171/-0)
  • .github/workflows/plugin-npm-release.yml (added, +214/-0)
  • .github/workflows/sandbox-common-smoke.yml (modified, +7/-2)
  • .github/workflows/stale.yml (modified, +12/-9)
  • .github/workflows/workflow-sanity.yml (modified, +30/-2)
  • .gitignore (modified, +18/-2)
  • .jscpd.json (added, +16/-0)
  • .npmignore (added, +2/-0)
  • .npmrc (modified, +3/-0)
  • .prettierignore (added, +1/-0)
  • .secrets.baseline (modified, +6/-6)
  • AGENTS.md (modified, +62/-142)
  • CHANGELOG.md (modified, +813/-131)
  • CONTRIBUTING.md (modified, +27/-4)
  • Dockerfile (modified, +41/-12)
  • Dockerfile.sandbox (modified, +1/-0)
  • Dockerfile.sandbox-browser (modified, +1/-0)
  • Dockerfile.sandbox-common (modified, +1/-0)
  • README.md (modified, +14/-14)
  • SECURITY.md (modified, +7/-0)
  • Swabble/Sources/SwabbleKit/WakeWordGate.swift (modified, +7/-13)
  • Swabble/Tests/SwabbleKitTests/WakeWordGateTests.swift (modified, +19/-0)
  • appcast.xml (modified, +175/-622)
  • apps/android/README.md (modified, +69/-3)
  • apps/android/app/build.gradle.kts (modified, +76/-7)
  • apps/android/app/proguard-rules.pro (modified, +0/-20)
  • apps/android/app/src/main/AndroidManifest.xml (modified, +2/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/MainActivity.kt (modified, +16/-6)
  • apps/android/app/src/main/java/ai/openclaw/app/MainViewModel.kt (modified, +170/-93)
  • apps/android/app/src/main/java/ai/openclaw/app/NodeApp.kt (modified, +12/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/NodeForegroundService.kt (modified, +6/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt (modified, +330/-58)
  • apps/android/app/src/main/java/ai/openclaw/app/PermissionRequester.kt (modified, +79/-21)
  • apps/android/app/src/main/java/ai/openclaw/app/SecurePrefs.kt (modified, +32/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt (modified, +64/-10)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/DeviceAuthStore.kt (modified, +2/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewaySession.kt (modified, +224/-19)
  • apps/android/app/src/main/java/ai/openclaw/app/node/A2UIHandler.kt (modified, +7/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/node/CallLogHandler.kt (added, +247/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/node/CameraCaptureManager.kt (modified, +36/-30)
  • apps/android/app/src/main/java/ai/openclaw/app/node/CameraHandler.kt (modified, +5/-3)
  • apps/android/app/src/main/java/ai/openclaw/app/node/CanvasActionTrust.kt (added, +50/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/node/CanvasController.kt (modified, +52/-14)
  • apps/android/app/src/main/java/ai/openclaw/app/node/ConnectionManager.kt (modified, +6/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/node/ContactsHandler.kt (modified, +5/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/node/DeviceHandler.kt (modified, +11/-2)
  • apps/android/app/src/main/java/ai/openclaw/app/node/InvokeCommandRegistry.kt (modified, +26/-5)
  • apps/android/app/src/main/java/ai/openclaw/app/node/InvokeDispatcher.kt (modified, +29/-3)
  • apps/android/app/src/main/java/ai/openclaw/app/node/LocationCaptureManager.kt (modified, +4/-9)
  • apps/android/app/src/main/java/ai/openclaw/app/node/LocationHandler.kt (modified, +75/-17)
  • apps/android/app/src/main/java/ai/openclaw/app/node/MotionHandler.kt (modified, +14/-18)
  • apps/android/app/src/main/java/ai/openclaw/app/node/PhotosHandler.kt (modified, +49/-34)
  • apps/android/app/src/main/java/ai/openclaw/app/node/SmsHandler.kt (modified, +12/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/node/SmsManager.kt (modified, +384/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/protocol/OpenClawCanvasA2UIAction.kt (modified, +6/-3)
  • apps/android/app/src/main/java/ai/openclaw/app/protocol/OpenClawProtocolConstants.kt (modified, +11/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/CanvasScreen.kt (modified, +34/-3)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/ConnectTabScreen.kt (modified, +182/-76)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/GatewayConfigResolver.kt (modified, +42/-7)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/GatewayDiagnostics.kt (added, +77/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/MobileUiTokens.kt (modified, +150/-24)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/OnboardingFlow.kt (modified, +580/-333)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/OpenClawTheme.kt (modified, +18/-1)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/PostOnboardingTabs.kt (modified, +54/-45)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/SettingsSheet.kt (modified, +320/-376)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/VoiceTabScreen.kt (modified, +48/-22)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/Base64ImageState.kt (modified, +1/-4)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatComposer.kt (modified, +63/-67)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatImageCodec.kt (added, +150/-0)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMarkdown.kt (modified, +21/-17)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMessageListCard.kt (modified, +16/-7)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMessageViews.kt (modified, +11/-8)
  • apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatSheetContent.kt (modified, +27/-95)

PR #52821: fix: load ~/.openclaw/.env for LaunchAgent environment variables (fixes #52771)

Description (problem / solution / changelog)

When installing the Gateway as a LaunchAgent on macOS, environment variables from ~/.openclaw/.env were not being included in the plist's EnvironmentVariables section. This caused API keys and other custom environment variables to be missing after reboot, resulting in HTTP 401 errors.

This fix explicitly loads the .env file during the gateway install process and merges its variables into the service environment with the correct precedence:

  1. .env file variables (lowest priority)
  2. Config env vars from openclaw.json
  3. Internal OPENCLAW_* variables (highest priority)

Fixes #52771

Changed files

  • src/commands/daemon-install-helpers.ts (modified, +62/-5)

Code Example

Output of `/usr/libexec/PlistBuddy -c "Print :EnvironmentVariables"` after running `openclaw gateway install --force` on v2026.3.13:

Dict {
    PATH = /Users/labkit01/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
    TMPDIR = /var/folders/x6/g1fsr23d69dfhqzr4kb06j940000gn/T/
    HOME = /Users/labkit01
    OPENCLAW_SERVICE_MARKER = openclaw
    NODE_EXTRA_CA_CERTS = /etc/ssl/cert.pem
    NODE_USE_SYSTEM_CA = 1
    OPENCLAW_WINDOWS_TASK_NAME = OpenClaw Gateway
    OPENCLAW_LAUNCHD_LABEL = ai.openclaw.gateway
    OPENCLAW_SYSTEMD_UNIT = openclaw-gateway.service
    OPENCLAW_GATEWAY_PORT = 18789
    OPENCLAW_SERVICE_VERSION = 2026.3.13
    OPENCLAW_SERVICE_KIND = gateway
}

No API keys present. Only internal OPENCLAW_* variables written by gateway install.
ANTHROPIC_API_KEY, OPENAI_API_KEY, BRAVE_SEARCH_API_KEY, MOONSHOT_API_KEY all absent.

---

cat > ~/openclaw-gateway-wrapper.sh << 'EOF'
#!/bin/bash
# Workaround for openclaw/openclaw#13340
set -a
source "$HOME/.openclaw/.env"
set +a

NODE=/opt/homebrew/opt/node/bin/node
OPENCLAW_DIR=/opt/homebrew/lib/node_modules/openclaw/dist

if [ -f "$OPENCLAW_DIR/entry.js" ]; then
  ENTRY="$OPENCLAW_DIR/entry.js"
else
  ENTRY="$OPENCLAW_DIR/index.js"
fi

exec "$NODE" "$ENTRY" gateway --port 18789
EOF
chmod 755 ~/openclaw-gateway-wrapper.sh

---

/usr/libexec/PlistBuddy -c "Delete :ProgramArguments" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
/usr/libexec/PlistBuddy -c "Add :ProgramArguments array" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
/usr/libexec/PlistBuddy -c "Add :ProgramArguments:0 string $HOME/openclaw-gateway-wrapper.sh" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
launchctl bootout gui/$(id -u) ai.openclaw.gateway
sleep 3
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Summary

Relates to: #13340 (locked), PR: #26567

Reopening per the bot's instruction on #13340: "If you are absolutely sure it still happens on the latest release, open a new issue with fresh repro steps."

openclaw gateway install --force does not write API keys into the LaunchAgent plist on v2026.3.13, causing all providers to return HTTP 401 after any reboot or gateway restart.

Steps to reproduce

Repro steps:

  1. Store API keys in ~/.openclaw/.env with variable references in openclaw.json
  2. Run openclaw gateway install --force
  3. Check plist: /usr/libexec/PlistBuddy -c "Print :EnvironmentVariables" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
  4. API keys are absent entirely — only OPENCLAW_* internal variables are present
  5. Reboot or allow launchd to restart the gateway
  6. All API providers return HTTP 401

Expected behavior

API keys stored in ~/.openclaw/.env are written into the LaunchAgent plist EnvironmentVariables section by gateway install, so the gateway process starts with valid credentials after a reboot or launchd restart.

Actual behavior

The plist EnvironmentVariables section contains only internal OPENCLAW_* variables. User API keys are absent entirely. On reboot, launchd starts the gateway with no credentials and all provider calls return HTTP 401.

OpenClaw version

2026.3.13

Operating system

macOS 15.3.1 (arm64, Apple Silicon)

Install method

npm global

Model

NOT_ENOUGH_INFO

Provider / routing chain

openclaw -> Anthropic / OpenAI / Brave Search (direct)

Additional provider/model setup details

Additional finding: loadDotEnv override: false makes the plist authoritative

Even when ~/.openclaw/.env is populated with valid keys, the gateway does not use them after a clean launchd start. OpenClaw's loadDotEnv initialises with override: false, meaning environment variables already present in the process environment (injected by launchd from the plist) take precedence over .env values. Since the plist has no API keys, the gateway starts with empty credentials. .env cannot fill the gap because override: false prevents it from overwriting the (absent but already-evaluated) environment.

Additional finding: openclaw update also changed the entry point filename

During testing, openclaw update changed the gateway entry point from index.js to entry.js in /opt/homebrew/lib/node_modules/openclaw/dist/. Any hardcoded path in a post-install patch script breaks silently on update.

Logs, screenshots, and evidence

Output of `/usr/libexec/PlistBuddy -c "Print :EnvironmentVariables"` after running `openclaw gateway install --force` on v2026.3.13:

Dict {
    PATH = /Users/labkit01/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
    TMPDIR = /var/folders/x6/g1fsr23d69dfhqzr4kb06j940000gn/T/
    HOME = /Users/labkit01
    OPENCLAW_SERVICE_MARKER = openclaw
    NODE_EXTRA_CA_CERTS = /etc/ssl/cert.pem
    NODE_USE_SYSTEM_CA = 1
    OPENCLAW_WINDOWS_TASK_NAME = OpenClaw Gateway
    OPENCLAW_LAUNCHD_LABEL = ai.openclaw.gateway
    OPENCLAW_SYSTEMD_UNIT = openclaw-gateway.service
    OPENCLAW_GATEWAY_PORT = 18789
    OPENCLAW_SERVICE_VERSION = 2026.3.13
    OPENCLAW_SERVICE_KIND = gateway
}

No API keys present. Only internal OPENCLAW_* variables written by gateway install.
ANTHROPIC_API_KEY, OPENAI_API_KEY, BRAVE_SEARCH_API_KEY, MOONSHOT_API_KEY all absent.

Impact and severity

Affected: Any macOS user managing API credentials via .env with LaunchAgent-managed gateway. Severity: Critical — blocks all agent functionality after reboot. Frequency: Always reproducible. Hit twice in 12 hours on 2026-03-22/23. Consequence: Complete provider authentication failure. Gateway appears healthy but every model call returns 401.

Additional information

Relates to #13340 (locked, closed as stale). PR #26567 addresses the root cause — please prioritise merging.

Workaround that survives openclaw update (verified)

Step 1: Create the wrapper script

cat > ~/openclaw-gateway-wrapper.sh << 'EOF'
#!/bin/bash
# Workaround for openclaw/openclaw#13340
set -a
source "$HOME/.openclaw/.env"
set +a

NODE=/opt/homebrew/opt/node/bin/node
OPENCLAW_DIR=/opt/homebrew/lib/node_modules/openclaw/dist

if [ -f "$OPENCLAW_DIR/entry.js" ]; then
  ENTRY="$OPENCLAW_DIR/entry.js"
else
  ENTRY="$OPENCLAW_DIR/index.js"
fi

exec "$NODE" "$ENTRY" gateway --port 18789
EOF
chmod 755 ~/openclaw-gateway-wrapper.sh

Note: openclaw gateway start does not run in foreground under launchd — node must be invoked directly.

Step 2: Point the plist at the wrapper (run after every openclaw update)

/usr/libexec/PlistBuddy -c "Delete :ProgramArguments" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
/usr/libexec/PlistBuddy -c "Add :ProgramArguments array" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
/usr/libexec/PlistBuddy -c "Add :ProgramArguments:0 string $HOME/openclaw-gateway-wrapper.sh" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
launchctl bootout gui/$(id -u) ai.openclaw.gateway
sleep 3
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist

Verified: all three API providers returned HTTP 200 after a full openclaw update cycle with this wrapper in place.

extent analysis

Fix Plan

To resolve the issue of API keys not being written into the LaunchAgent plist, we need to modify the openclaw gateway install command to include the API keys from the .env file. However, given the provided workaround, we will focus on refining and implementing it as a more robust solution.

Step 1: Create a Wrapper Script

Create a wrapper script that sources the .env file and then runs the OpenClaw gateway. This ensures that the environment variables (API keys) are set before the gateway starts.

cat > ~/openclaw-gateway-wrapper.sh << 'EOF'
#!/bin/bash
# Workaround for openclaw/openclaw#13340
set -a
source "$HOME/.openclaw/.env"
set +a

NODE=/opt/homebrew/opt/node/bin/node
OPENCLAW_DIR=/opt/homebrew/lib/node_modules/openclaw/dist

if [ -f "$OPENCLAW_DIR/entry.js" ]; then
  ENTRY="$OPENCLAW_DIR/entry.js"
else
  ENTRY="$OPENCLAW_DIR/index.js"
fi

exec "$NODE" "$ENTRY" gateway --port 18789
EOF
chmod 755 ~/openclaw-gateway-wrapper.sh

Step 2: Update the LaunchAgent plist

Modify the LaunchAgent plist to use the wrapper script instead of directly running the OpenClaw gateway.

/usr/libexec/PlistBuddy -c "Delete :ProgramArguments" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
/usr/libexec/PlistBuddy -c "Add :ProgramArguments array" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
/usr/libexec/PlistBuddy -c "Add :ProgramArguments:0 string $HOME/openclaw-gateway-wrapper.sh" ~/Library/LaunchAgents/ai.openclaw.gateway.plist
launchctl bootout gui/$(id -u) ai.openclaw.gateway
sleep 3
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist

Verification

After implementing the wrapper script and updating the LaunchAgent plist, verify that the API keys are correctly set and the OpenClaw gateway functions as expected by checking the following:

  • The presence of API keys in the environment when the gateway is running.
  • Successful responses (HTTP 200) from API providers after a reboot or gateway restart.

Extra Tips

  • Ensure the .env file is correctly formatted and contains all necessary API keys.
  • After running openclaw update, reapply the wrapper script and plist modifications to maintain functionality.
  • Consider automating the process of updating the wrapper script and plist after openclaw update to prevent manual intervention.

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…

FAQ

Expected behavior

API keys stored in ~/.openclaw/.env are written into the LaunchAgent plist EnvironmentVariables section by gateway install, so the gateway process starts with valid credentials after a reboot or launchd restart.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING