Skip to content

Commit 8a7adc0

Browse files
committed
fix(kernel-cli): move LOG_LEVELS above file-scope logger to avoid TDZ
The demo branch's file-scope logger construction hit a temporal- dead-zone reference because `makeFileTransport(logPath, resolveMinLogLevel())` runs at module top and `resolveMinLogLevel` uses `LOG_LEVELS`, which was declared as a `const` further down the file. Function declarations hoist but `const` bindings stay in TDZ until execution reaches them, so the daemon child crashed at module init with: ReferenceError: Cannot access 'LOG_LEVELS' before initialization The crash happened before the fatal-handler install ran, and the child was spawned with stdio: 'ignore', so the failure surfaced only as a 30-second polling timeout ("Daemon did not start"). Move `LOG_LEVELS`, `LogLevelName`, and `resolveMinLogLevel()` above the module-scope logger construction. Fixes the demo branch; PR #966 (main-based) is unaffected because its transport factory doesn't reference `LOG_LEVELS`.
1 parent ec393ff commit 8a7adc0

1 file changed

Lines changed: 30 additions & 27 deletions

File tree

packages/kernel-cli/src/commands/daemon-entry.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,36 @@ import { join } from 'node:path';
1111
import { getOcapHome } from '../ocap-home.ts';
1212
import { isProcessAlive } from '../utils.ts';
1313

14+
// Mirror of @metamask/logger's level ordering (`logLevels` is not part
15+
// of the package's public surface). Higher numbers are more severe.
16+
// Declared above the file-scope logger construction so the transport
17+
// factory doesn't hit a temporal-dead-zone reference when it's called
18+
// during module init.
19+
const LOG_LEVELS = {
20+
debug: 1,
21+
info: 2,
22+
log: 3,
23+
warn: 4,
24+
error: 5,
25+
} as const;
26+
27+
type LogLevelName = keyof typeof LOG_LEVELS;
28+
29+
/**
30+
* Resolve the daemon's minimum log level from `OCAP_DAEMON_LOG_LEVEL`.
31+
* Defaults to `info` so noisy `debug` entries (refcount churn etc.)
32+
* are dropped; set the env var to `debug` to re-enable everything.
33+
*
34+
* @returns The minimum log level to record.
35+
*/
36+
function resolveMinLogLevel(): LogLevelName {
37+
const raw = process.env.OCAP_DAEMON_LOG_LEVEL;
38+
if (raw !== undefined && raw in LOG_LEVELS) {
39+
return raw as LogLevelName;
40+
}
41+
return 'info';
42+
}
43+
1444
const ocapDir = getOcapHome();
1545
const logPath = join(ocapDir, 'daemon.log');
1646
const logger = new Logger({
@@ -138,33 +168,6 @@ async function readDaemonPid(pidPath: string): Promise<number | undefined> {
138168
return Number.isFinite(pid) && pid > 0 ? pid : undefined;
139169
}
140170

141-
// Mirror of @metamask/logger's level ordering (`logLevels` is not part
142-
// of the package's public surface). Higher numbers are more severe.
143-
const LOG_LEVELS = {
144-
debug: 1,
145-
info: 2,
146-
log: 3,
147-
warn: 4,
148-
error: 5,
149-
} as const;
150-
151-
type LogLevelName = keyof typeof LOG_LEVELS;
152-
153-
/**
154-
* Resolve the daemon's minimum log level from `OCAP_DAEMON_LOG_LEVEL`.
155-
* Defaults to `info` so noisy `debug` entries (refcount churn etc.)
156-
* are dropped; set the env var to `debug` to re-enable everything.
157-
*
158-
* @returns The minimum log level to record.
159-
*/
160-
function resolveMinLogLevel(): LogLevelName {
161-
const raw = process.env.OCAP_DAEMON_LOG_LEVEL;
162-
if (raw !== undefined && raw in LOG_LEVELS) {
163-
return raw as LogLevelName;
164-
}
165-
return 'info';
166-
}
167-
168171
/**
169172
* Create a file transport that writes logs to a file, filtering out
170173
* entries below `minLevel`.

0 commit comments

Comments
 (0)