Skip to content

macOS app: dashboard fails silently with unresolved ${OPENCLAW_GATEWAY_TOKEN} placeholder when env var not in app's environment, with no in-app recovery path #101286

Description

@redasadki

Summary

The macOS OpenClaw.app dashboard fails to load, showing "Dashboard unavailable / Could not connect to the server", with the connect URL containing a literal double-URL-encoded, unresolved config placeholder instead of the actual gateway token:

http://127.0.0.1:18789/#token=$%257BOPENCLAW_GATEWAY_TOKEN%257D

Decoding twice: %257B%7B{, giving ${OPENCLAW_GATEWAY_TOKEN} — the literal ${VAR} placeholder string from openclaw.json, not the resolved secret value.

Environment

  • OpenClaw 2026.6.11 (gateway + CLI, pnpm/npm-global installs)
  • macOS OpenClaw.app (native menu-bar/dashboard app), same version
  • Gateway running via a per-user LaunchAgent (launchd), local mode (ws://127.0.0.1:18789)
  • gateway.auth.token in openclaw.json is stored as a template reference: "${OPENCLAW_GATEWAY_TOKEN}", with the actual secret value in a .env file consumed by the gateway's LaunchAgent EnvironmentVariables / service-env file.

Steps to reproduce

  1. Configure gateway.auth.token in openclaw.json as "${OPENCLAW_GATEWAY_TOKEN}", with the real token supplied only via the gateway service's own environment (e.g. LaunchAgent EnvironmentVariables, not the global user/session environment).
  2. Launch OpenClaw.app from the Dock/Finder (i.e., not from a shell that has OPENCLAW_GATEWAY_TOKEN exported).
  3. Open the dashboard from the app.

Expected behavior

Either:

  • The app should ask the running gateway for its dashboard URL (with token already resolved server-side), rather than resolving ${OPENCLAW_GATEWAY_TOKEN} itself from its own process environment; or
  • If the app must resolve the token client-side, it should read it from the same source the gateway process uses (e.g. shared service-env file) rather than only the ambient GUI-launchd environment; or
  • At minimum, if the token placeholder cannot be resolved, the app should show a clear, actionable error (e.g. "Gateway token is not configured/resolvable from this app; open Settings to set it manually") instead of silently passing the literal ${VAR} string into the connect URL.

Actual behavior

  • The app resolves the token from its own process environment only.
  • macOS GUI apps launched via Dock/Finder do not inherit env vars that are scoped only to a separate per-service LaunchAgent (a well-known macOS launchd behavior, not an OpenClaw bug in itself) — so OPENCLAW_GATEWAY_TOKEN is typically absent from the app's environment even though the gateway process has it.
  • When resolution fails, the app does not fall back or surface a clear error. It substitutes the literal unresolved string ${OPENCLAW_GATEWAY_TOKEN}, URL-encodes it (apparently twice), and uses it as the #token= fragment when opening the dashboard URL.
  • Result: dashboard permanently shows "Could not connect to the server", and because the dashboard itself fails to load, the in-app Settings screen used to manually re-enter the token is also unreachable — there is no way to recover from within the app UI.
  • Re-entering the token via Settings when reachable, or fully quitting/relaunching the app, does not durably fix this, because the underlying env-resolution gap is still present on next launch (or after any process working-directory/environment reset).

Impact

  • Complete lockout from the dashboard/Settings UI in this configuration, with no in-app recovery path.
  • Silent failure mode (unresolved placeholder passed through) makes the actual cause (env var not visible to the app) very hard to diagnose from the UI alone; it required inspecting the running gateway's logs/auth-rate-limit state and then binary-searching the app bundle's strings/config-loading logic to find the real cause.

Suggested fixes (any one would resolve this)

  1. Prefer fetching the effective/resolved dashboard URL (with token) from the gateway's own API/IPC channel, rather than templating the URL from local config + local env.
  2. If client-side resolution of ${ENV_VAR} placeholders is required, document (or auto-detect) that the referenced env var must be present in the broader user/login environment (e.g. via launchctl setenv), not only inside a specific LaunchAgent's environment block — and ideally read from the same resolved service-env file the gateway itself uses.
  3. Add explicit error handling: if a ${...} placeholder in gateway.auth.token cannot be resolved to a real value, do not proceed to construct/open a dashboard URL with the raw placeholder. Show an explicit "token not resolvable" error with a path to fix it (env var name expected, and/or an option to enter a literal token override in Settings) — and ensure this error path itself does not depend on the dashboard already having loaded.

Notes

  • This is a config/UX robustness issue in the app's env-driven token resolution and error handling, not a report of a specific typo in any one user's config — the underlying scenario (secret sourced from a LaunchAgent-scoped env var, app launched via Dock/Finder without that env var visible) is a common and expected macOS deployment pattern for this kind of app.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Emergency: data loss, security bypass, crash loop, or unusable core runtime.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:ux-release-blockerA non-technical user is blocked without terminal, logs, config, or support.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions