can1357/oh-my-pi · error
Invalid readiness regex: ${error instanceof Error ? error.me
Error message
Invalid readiness regex: ${error instanceof Error ? error.message : String(error)} What it means
DaemonBroker.start validates spec.ready.log by compiling it with new RegExp(pattern, "u") before launching the daemon. If the pattern is syntactically invalid (or uses features incompatible with the 'u' flag), the launch is aborted with this message so the failure surfaces before a process is spawned. The underlying RegExp syntax error message is appended.
Source
Thrown at packages/coding-agent/src/launch/broker.ts:628
if (this.#startingNames.has(spec.name)) {
throw new Error(`Daemon ${spec.name} is already starting`);
}
this.#startingNames.add(spec.name);
let record: ManagedDaemon;
try {
const existing = this.#records.get(spec.name);
if (existing) await this.#refreshDetached(existing);
if (existing && !terminalState(existing.snapshot.state)) {
throw new Error(`Daemon ${spec.name} is already ${existing.snapshot.state}`);
}
if (existing && existing.pendingCompletions.length > 0) {
throw new Error(`Daemon ${spec.name} has unacknowledged completion notifications`);
}
if (spec.ready?.log) {
try {
new RegExp(spec.ready.log, "u");
} catch (error) {
throw new Error(`Invalid readiness regex: ${error instanceof Error ? error.message : String(error)}`);
}
}
const stat = await fs.stat(spec.cwd);
if (!stat.isDirectory()) throw new Error(`Daemon cwd is not a directory: ${spec.cwd}`);
const dir = path.join(this.#runtimeDir, "daemons", spec.name);
const now = Date.now();
record = {
spec,
snapshot: {
name: spec.name,
id: crypto.randomUUID(),
state: "starting",
createdAt: now,
startedAt: now,
restartCount: 0,
outputBytes: 0,
owner,
persist: spec.persist,View on GitHub (pinned to 9690622007)
Solutions
- Fix the ready.log pattern so it compiles under the 'u' flag; test with `new RegExp(pattern, "u")` locally.
- Escape special characters properly (in JSON config, double the backslashes: "\\d+").
- Remove ready.log entirely if log-based readiness detection is not needed.
Example fix
// before
ready: { log: "listening on (port \d+" }
// after
ready: { log: "listening on \\(port \\d+" } // compiles under new RegExp(p, "u") Defensive patterns
Strategy: validation
Validate before calling
if (spec.ready?.log) {
try { new RegExp(spec.ready.log, "u"); }
catch (e) { throw new Error(`Bad ready.log in spec '${spec.name}': ${e.message}`); }
} Type guard
function isValidRegexU(p: unknown): p is string {
if (typeof p !== "string") return false;
try { new RegExp(p, "u"); return true; } catch { return false; }
} Try / catch
try {
await broker.start(spec);
} catch (err) {
if (err instanceof Error && err.message.startsWith("Invalid readiness regex:")) {
// fix or drop spec.ready.log, then retry
} else throw err;
} Prevention
- Validate readiness regexes in a unit test that compiles every pattern in your daemon config.
- Remember JSON requires doubled backslashes for regex escapes.
- Prefer simple substring-free patterns and test them against real daemon log lines.
When it happens
Trigger: Passing a daemon spec whose ready.log string is not a valid regular expression — e.g. unescaped '(' or '[', dangling quantifier like '++', or a lone surrogate that the 'u' flag rejects.
Common situations: Hand-written readiness patterns in config files/JSON where backslashes were not escaped (\d becomes d), or patterns copied from PCRE with syntax V8's 'u' mode rejects (e.g. invalid unicode escapes).
Related errors
- err.to_string() (invalid regex pattern)
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id wit
- ${name} path does not exist: ${trimmed}
- Anthropic thinking budget requires max_tokens greater than $
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/0cecf6ab7053fd98.
Report an issue: GitHub.