Why OpenClaw 2.22 Keeps Asking for exec Approvals — A Fly.io Upgrade Postmortem

Loading...


I recently upgraded my Fly.io OpenClaw machine from 2026.2.17 → 2026.2.22 and ended up debugging well past midnight. This post is the full postmortem — for my future self and for anyone else running OpenClaw on Fly.io.

Background: My OpenClaw Setup

I run a Fly.io machine called openclaw-dab-test with:

  • Region: nrt (Tokyo)
  • VM: shared-cpu-2x, 4096MB RAM
  • Volume: openclaw_data → /data (config, memory, workspace, cron jobs)

Before the upgrade, it was on OpenClaw 2026.2.17. npm latest was 2026.2.22.

Pitfall #1: The Dockerfile Assumed Local Source

The original infra/fly/Dockerfile built from local source:

COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY patches ./patches
COPY scripts ./scripts
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:build

That means deployment required running flyctl deploy inside the OpenClaw repo itself (the whole repo is the build context). I no longer had the local source, so this Dockerfile was useless.

Fix: clone from GitHub during build

FROM node:22-bookworm

RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"

RUN corepack enable

WORKDIR /app

RUN git clone --depth 1 https://github.com/openclaw/openclaw.git .

RUN pnpm install --frozen-lockfile
RUN pnpm build
ENV OPENCLAW_PREFER_PNPM=1
RUN pnpm ui:build

ENV NODE_ENV=production
RUN chown -R node:node /app
USER node

CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"]

Now every flyctl deploy pulls the latest source automatically.

Why Not Just npm install openclaw@latest?

I tried. It gets messy fast.

1) Git missing

npm error enoent An unknown git error occurred
npm error syscall spawn git

Some dependencies use git URLs. The bookworm-slim image doesn’t include git.

2) CA certificates missing

fatal: unable to access '...': server certificate verification failed.
CAfile: none CRLfile: none

No ca-certificates → git can’t verify HTTPS.

3) @discordjs/opus needs Python + build tools

npm error node-pre-gyp WARN Pre-built binaries not installable
npm error gyp ERR! find Python Python is not set

OpenClaw depends on @discordjs/opus. npm tries to compile it, fails without Python.

Here’s the key difference: OpenClaw’s package.json contains:

"pnpm": {
 "onlyBuiltDependencies": [
 "@lydell/node-pty",
 "@whiskeysockets/baileys",
 "esbuild",
 "sharp",
 ...
 ]
}

@discordjs/opus isn’t in the list, so pnpm skips building it. npm doesn’t respect this, so it tries to build and fails.

Conclusion: npm can work, but requires more deps (Python, build-essential). pnpm-from-source is cleaner and faster.

Upgrade Success… Then the Config Broke

After upgrading, OpenClaw 2026.2.22 booted fine — until I used the exec tool. It kept asking for approvals.

I tried to disable it like this:

c['tools']['exec'] = {
 'enabled': True,
 'security': 'full',
 'ask': 'off'
}

Boom:

Config invalid
Problem:
 - tools.exec: Unrecognized key: "enabled"
Run: openclaw doctor --fix

enabled is not a valid key. My bad.

Then the machine entered a crash loop — invalid config on startup, exit code 1, restart, repeat. No SSH, no flyctl machine exec.

Recovery: temporary startup command

Use flyctl machine update --command to fix config before launching:

flyctl machine update <machine-id> \
 --command 'bash -c "node openclaw.mjs doctor --fix 2>/dev/null; node openclaw.mjs gateway --allow-unconfigured --port 3000 --bind lan"' \
 -a openclaw-dab-test --yes

On boot:

  • doctor --fix removes invalid keys
  • gateway starts on port 3000
  • health check passes

After recovery, redeploy to restore the original fly.toml command.

Correct exec config

"tools": {
 "exec": {
 "security": "full",
 "ask": "off"
 }
}

No enabled. In OpenClaw 2.22, tools.exec only accepts security and ask. To disable approval prompts, set "ask": "off".

2.22 exec security changes

The changelog notes stricter exec analysis:

Security/Exec approvals: treat env and shell-dispatch wrappers as transparent during allowlist analysis on node-host and macOS companion paths so policy checks match the effective executable/inline shell payload instead of the wrapper binary, blocking wrapper-smuggled allowlist bypasses.

Security/Exec approvals: require explicit safe-bin profiles for tools.exec.safeBins entries in allowlist mode (remove generic safe-bin profile fallback)…

So if you suddenly get more exec approvals, double-check both ask: "off" and your security profile.

Pitfall #3: Post-reboot Amnesia

This existed before, but after upgrade it became obvious: every restart felt like a fresh boot. OpenClaw forgot everything unless I manually reloaded /data.

Root cause:

LocationContentsAfter reboot
/home/node/.openclaw/workspaceSOUL.md, USER.md, AGENTS.md❌ Reset to defaults
/data/MEMORY.md, memory/main.sqlite✅ Persisted (volume)

The workspace lived inside the container, not on the volume. So every restart wiped it.

Fix: move workspace to /data

Update config:

c['agents']['defaults']['workspace'] = '/data/workspace'

Then copy the current workspace:

flyctl machine exec <machine-id> "cp -r /home/node/.openclaw/workspace /data/workspace" -a openclaw-dab-test

After reboot, everything persists. No more re-reading files on every startup.

Upgrade Checklist (Fly.io)

cd infra/fly
flyctl deploy --wait-timeout 180

Because the Dockerfile now clones from GitHub, deploy always builds the latest version.

If Depot cache hits, build is fast. A clean build typically takes 5–10 minutes (pnpm install + TS compile + UI build).

Summary of Pitfalls

IssueCauseFix
Dockerfile required local sourceIt was designed for source buildsClone from GitHub during build
npm install failed (@discordjs/opus)npm ignores pnpm.onlyBuiltDependenciesUse pnpm-from-source
Config crash (enabled key)tools.exec.enabled not validUse only security + ask
Crash loop recoveryNo SSH / exec possibleTemporary flyctl machine update --command
Amnesia after rebootWorkspace not on volumeMove workspace to /data/workspace

Every pitfall is a one-time lesson. Hopefully this saves you a long night.