{"record":{"id":"0cecf6ab7053fd98","repo":"can1357/oh-my-pi","slug":"invalid-readiness-regex-error-instanceof-error","errorCode":null,"errorMessage":"Invalid readiness regex: ${error instanceof Error ? error.message : String(error)}","messagePattern":"Invalid readiness regex: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/launch/broker.ts","lineNumber":628,"sourceCode":"\t\tif (this.#startingNames.has(spec.name)) {\n\t\t\tthrow new Error(`Daemon ${spec.name} is already starting`);\n\t\t}\n\t\tthis.#startingNames.add(spec.name);\n\t\tlet record: ManagedDaemon;\n\t\ttry {\n\t\t\tconst existing = this.#records.get(spec.name);\n\t\t\tif (existing) await this.#refreshDetached(existing);\n\t\t\tif (existing && !terminalState(existing.snapshot.state)) {\n\t\t\t\tthrow new Error(`Daemon ${spec.name} is already ${existing.snapshot.state}`);\n\t\t\t}\n\t\t\tif (existing && existing.pendingCompletions.length > 0) {\n\t\t\t\tthrow new Error(`Daemon ${spec.name} has unacknowledged completion notifications`);\n\t\t\t}\n\t\t\tif (spec.ready?.log) {\n\t\t\t\ttry {\n\t\t\t\t\tnew RegExp(spec.ready.log, \"u\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new Error(`Invalid readiness regex: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst stat = await fs.stat(spec.cwd);\n\t\t\tif (!stat.isDirectory()) throw new Error(`Daemon cwd is not a directory: ${spec.cwd}`);\n\t\t\tconst dir = path.join(this.#runtimeDir, \"daemons\", spec.name);\n\t\t\tconst now = Date.now();\n\t\t\trecord = {\n\t\t\t\tspec,\n\t\t\t\tsnapshot: {\n\t\t\t\t\tname: spec.name,\n\t\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\t\tstate: \"starting\",\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tstartedAt: now,\n\t\t\t\t\trestartCount: 0,\n\t\t\t\t\toutputBytes: 0,\n\t\t\t\t\towner,\n\t\t\t\t\tpersist: spec.persist,","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/launch/broker.ts#L610-L646","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before\nready: { log: \"listening on (port \\d+\" }\n// after\nready: { log: \"listening on \\\\(port \\\\d+\" }  // compiles under new RegExp(p, \"u\")","handlingStrategy":"validation","validationCode":"if (spec.ready?.log) {\n  try { new RegExp(spec.ready.log, \"u\"); }\n  catch (e) { throw new Error(`Bad ready.log in spec '${spec.name}': ${e.message}`); }\n}","typeGuard":"function isValidRegexU(p: unknown): p is string {\n  if (typeof p !== \"string\") return false;\n  try { new RegExp(p, \"u\"); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  await broker.start(spec);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Invalid readiness regex:\")) {\n    // fix or drop spec.ready.log, then retry\n  } else throw err;\n}","preventionTips":["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."],"tags":["regex","validation","configuration"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}