Skip to content

macOS: env-generator.sh writes HOST_RAM_GB to .env but .env.schema.json has no entry — 503 on every PUT /api/settings/env #337

@yasinBursali

Description

@yasinBursali

Summary

On macOS Apple Silicon, dream-server/installers/macos/lib/env-generator.sh:170 unconditionally writes HOST_RAM_GB=<unified memory GB> to the install's .env. dream-server/.env.schema.json has no HOST_RAM_GB entry. Result: the schema-aware validator in _handle_env_update (and its /api/settings/env proxy api_settings_env_save) rejects every round-trip with 503 {"detail":{"message":"Unknown key: HOST_RAM_GB"}}.

No user on macOS can save anything from the dashboard Settings panel on a fresh install. The GET endpoint returns a schema-filtered values dict + empty raw (separate issue), so the dashboard UI can't even read its own starting state to send back.

Reproduction (fresh install, integration branch or main)

$ grep HOST_RAM /Volumes/X/dream-server-test/.env
HOST_RAM_GB=24

$ grep HOST_RAM /Volumes/X/dream-server-test/.env.schema.json
(no output)

$ curl -s -H "Authorization: Bearer \$KEY" http://127.0.0.1:3002/api/settings/env \
  | python3 -m json.tool | head -6
{
    "path": ".env",
    "raw": "",           ← empty, independent issue
    "values": {
        "DREAM_VERSION": "",
        ...
    }

$ python3 -c "
import json, urllib.request
raw = open('/Volumes/X/dream-server-test/.env').read()
req = urllib.request.Request(
    'http://127.0.0.1:3002/api/settings/env',
    method='PUT',
    headers={'Authorization': f'Bearer \$KEY', 'Content-Type': 'application/json'},
    data=json.dumps({'raw_text': raw}).encode(),
)
urllib.request.urlopen(req)
"
urllib.error.HTTPError: HTTP Error 503: Service Unavailable
body: {\"detail\":{\"message\":\"Unknown key: HOST_RAM_GB\"}}

File on disk is unchanged because the validator rejects the input upfront. This is actually the "fail-safe" branch of a different bug — see below.

Why this is specifically user-blocking on Mac

On Linux installs, env-generator.sh doesn't run. The Linux install path uses installers/phases/*.sh which don't write HOST_RAM_GB (it's an Apple-Silicon-only unified-memory hint used by llama.cpp via the --n-gpu-layers / metal backend). So the schema gap is invisible on Linux — every key written by the Linux installer IS in the schema, so round-trips succeed (and hit #335's .env.example rebuild bug instead).

On Mac, the first thing _handle_env_update does after parsing the raw text is walk every key through .env.schema.json, and the first unknown key is HOST_RAM_GB — which is every key the user could ever want to save. Net effect: Settings panel round-trip is completely broken on Mac on a fresh install.

Why this was missed by the schema-validator tests

  • dashboard-api/tests/test_host_agent.py::TestHandleEnvUpdate uses a _FakeHandler fixture that writes a synthetic minimal schema with just DREAM_AGENT_KEY and GGUF_FILE (test_host_agent.py:278–290). It never loads the real production .env.schema.json, so no test exercises the real schema's actual key set against a real installer output.
  • validate-env.sh (Linux installer phase 06) is where a canonical "does .env match .env.schema.json?" check lives per the project memory note — but it's only run on Linux. Mac installs skip it entirely because install-macos.sh doesn't call it.

So the gap persists undetected: no unit test reads the real schema, no installer phase validates it on Mac.

Platform matrix

Platform .env has HOST_RAM_GB? /api/settings/env PUT result
macOS Apple Silicon YES (written by env-generator.sh:170) 503 Unknown key
macOS Intel (if supported) probably YES (same env-generator path) 503 Unknown key
Linux NVIDIA NO 200 + hits #335 (.env.example rebuild bug drops keys)
Linux AMD NO 200 + hits #335
WSL2 NO 200 + hits #335

Proposed fix (pick one)

Option A — add HOST_RAM_GB to .env.schema.json (least invasive)

 {
   "properties": {
     ...
+    \"HOST_RAM_GB\": {
+      \"type\": \"integer\",
+      \"description\": \"Unified-memory system RAM in GB (Apple Silicon). Written by env-generator.sh; used by llama.cpp metal backend.\",
+      \"minimum\": 1
+    },
     ...
   }
 }

Plus the matching entry in .env.example so the _render_env_from_values rebuild path picks it up.

Also audit env-generator.sh for any OTHER Mac-only keys that aren't in the schema (I saw at least HOST_GPU_CORES, HOST_CHIP referenced in the memory note, though those seem to be intentionally not written now — worth a double-check).

Option B — make _handle_env_update's unknown-key check non-fatal

Downgrade unknown-key from "reject request" to "preserve verbatim, log warning." This is what users actually want: the settings panel shouldn't be the schema police. Keeps installer-generated values intact across round-trips.

Option C — byte-perfect round-trip

Same as #335's Option B: if raw_text is provided, validate but don't re-render. Write the input bytes verbatim after validation. Avoids ALL the rebuild-vs-preserve tradeoffs.

Recommendation: Option A plus Option C. Option A closes the immediate schema gap (one-line fix), Option C closes the broader class of "rebuild ate my keys" surprises across both platforms.

Not a regression from any of the 17 open PRs

Confirmed pre-existing. HOST_RAM_GB isn't touched by any of Light-Heart-Labs#893Light-Heart-Labs#909. The schema file isn't touched by any of the 17 PRs (grep confirmed). This is pre-existing behavior on Light-Heart-Labs/DreamServer main. I surfaced it while runtime-testing PR Light-Heart-Labs#908 (/v1/env/update endpoint) and PR #335's dashboard-api api_settings_env_save path during integration validation.

Related issues on this fork

Environment

  • macOS Darwin 25.2.0, Apple Silicon M4, 24 GB unified memory
  • Install at /Volumes/X/dream-server-test
  • Integration branch = upstream/main + all 17 open yasinBursali PRs (fix(models): platform-aware activation + download cancel Light-Heart-Labs/DreamServer#893–909) merged --no-ff
  • Schema file: dream-server/.env.schema.json — no HOST_RAM_GB entry in the top-level properties map
  • Writer: dream-server/installers/macos/lib/env-generator.sh:170HOST_RAM_GB=\${SYSTEM_RAM_GB}

Filing on the fork per project convention.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions