can1357/oh-my-pi · critical

Daemon broker environment is incomplete

Error message

Daemon broker environment is incomplete

What it means

startDaemonBrokerFromEnvironment runs inside the spawned daemon broker worker process and reads DAEMON_PROJECT_DIR_ENV and DAEMON_RUNTIME_DIR_ENV from the environment. If either is missing or empty, the broker cannot know which project to serve or where to keep runtime state, so it throws immediately at startup.

Source

Thrown at packages/coding-agent/src/launch/broker.ts:1385

					this.#scheduleIdleShutdown();
					return;
				}
				if (this.#clients.size === 0) await this.shutdown();
			})();
		}, this.#idleGraceMs);
	}
}

export interface DaemonBrokerStartOptions {
	/** Base of the exponential child-restart backoff. */
	restartBackoffBaseMs?: number;
}

/** Start the detached project or global daemon broker selected by the CLI worker host. */
export async function startDaemonBrokerFromEnvironment(options: DaemonBrokerStartOptions = {}): Promise<void> {
	const projectDir = process.env[DAEMON_PROJECT_DIR_ENV];
	const runtimeDir = process.env[DAEMON_RUNTIME_DIR_ENV];
	if (!projectDir || !runtimeDir) throw new Error("Daemon broker environment is incomplete");
	delete process.env[DAEMON_PROJECT_DIR_ENV];
	delete process.env[DAEMON_RUNTIME_DIR_ENV];
	const rawGrace = process.env[DAEMON_IDLE_GRACE_ENV];
	delete process.env[DAEMON_IDLE_GRACE_ENV];
	const parsedGrace = rawGrace === undefined ? DEFAULT_IDLE_GRACE_MS : Number.parseInt(rawGrace, 10);
	const idleGraceMs = Number.isFinite(parsedGrace) && parsedGrace >= 0 ? parsedGrace : DEFAULT_IDLE_GRACE_MS;
	const requestedRestartBackoffBaseMs = options.restartBackoffBaseMs ?? RESTART_BACKOFF_BASE_MS;
	const restartBackoffBaseMs =
		Number.isFinite(requestedRestartBackoffBaseMs) && requestedRestartBackoffBaseMs >= 0
			? requestedRestartBackoffBaseMs
			: RESTART_BACKOFF_BASE_MS;
	await fs.mkdir(runtimeDir, { recursive: true, mode: 0o700 });
	const lease = await acquireBrokerLease(runtimeDir);
	if (!lease) return;
	setProcessName("omp daemon broker");
	// Record the scope's project dir so `omp ps` can map this hash-keyed runtime
	// dir back to its project (and derive the Windows pipe name) offline.
	void writeDaemonScopeMeta(runtimeDir, projectDir).catch(error => {

View on GitHub (pinned to 9690622007)

Solutions

  1. Ensure the spawn site passes the env overlay containing DAEMON_PROJECT_DIR_ENV and DAEMON_RUNTIME_DIR_ENV (see #spawnBroker)
  2. Launch the broker via the library's worker spawn path instead of starting the worker module manually
  3. Log/verify the child process env at spawn time to confirm both vars are present

Example fix

// before
Bun.spawn([workerCmd], { env: { ...process.env } });
// after
Bun.spawn([workerCmd], { env: { ...process.env, [DAEMON_PROJECT_DIR_ENV]: projectDir, [DAEMON_RUNTIME_DIR_ENV]: runtimeDir } });
Defensive patterns

Strategy: validation

Validate before calling

const projectDir = process.env.DAEMON_PROJECT_DIR;
const runtimeDir = process.env.DAEMON_RUNTIME_DIR;
if (!projectDir || !runtimeDir) throw new Error('refusing to spawn broker worker: missing DAEMON_PROJECT_DIR/DAEMON_RUNTIME_DIR');

Try / catch

try {
  await startDaemonBrokerFromEnvironment();
} catch (err) {
  if (err.message.includes('environment is incomplete')) {
    logger.error('broker worker spawned without required env vars', { missing: ['DAEMON_PROJECT_DIR','DAEMON_RUNTIME_DIR'].filter(k => !process.env[k]) });
  }
  throw err;
}

Prevention

When it happens

Trigger: Spawning the broker worker without setting both DAEMON_PROJECT_DIR_ENV and DAEMON_RUNTIME_DIR_ENV env vars; env vars set to empty strings; launching the worker entry manually without going through DaemonBrokerClient spawn plumbing.

Common situations: Custom process managers (systemd, docker) dropping env vars; running the worker entry directly in a REPL or test; stale spawn code written before the env overlay was added.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4300a179703d59b7. Report an issue: GitHub.