can1357/oh-my-pi · error
Invalid log regex: ${error instanceof Error ? error.message
Error message
Invalid log regex: ${error instanceof Error ? error.message : String(error)} What it means
The broker's readFiles log reader accepts an optional `grep` parameter compiled into a RegExp with the 'u' (unicode) flag. If `new RegExp(grep, 'u')` throws — invalid pattern syntax, or constructs illegal under the unicode flag such as unescaped lone surrogate pairs or invalid \\u escapes — the raw RegExp engine error is rethrown wrapped as 'Invalid log regex: <detail>' so callers know the filter string, not the log data, is at fault.
Source
Thrown at packages/coding-agent/src/launch/broker.ts:265
logPath: string,
previousPath: string,
head: boolean,
lines: number,
cursor: number,
grep?: string,
): Promise<DaemonLogRead> {
const [previous, current] = await Promise.all([fileTextSlice(previousPath, head), fileTextSlice(logPath, head)]);
const combined = `${previous}${previous && current && !previous.endsWith("\n") ? "\n" : ""}${current}`;
const terminalOutput = head
? truncateHeadBytes(combined, LOG_READ_BYTES).text
: truncateTailBytes(combined, LOG_READ_BYTES).text;
let text = sanitizeText(terminalOutput);
if (grep) {
let pattern: RegExp;
try {
pattern = new RegExp(grep, "u");
} catch (error) {
throw new Error(`Invalid log regex: ${error instanceof Error ? error.message : String(error)}`);
}
text = text
.split("\n")
.filter(line => pattern.test(line))
.join("\n");
}
const options = { maxLines: lines, maxBytes: 256 * 1024 };
return {
text: head ? truncateHead(text, options).content : truncateTail(text, options).content,
terminalOutput,
cursor,
};
}
async #rotate(): Promise<void> {
await this.#writer.end();
await fs.rm(this.#previousPath, { force: true });
await fs.rename(this.#path, this.#previousPath);View on GitHub (pinned to 9690622007)
Solutions
- Fix the pattern syntax reported after 'Invalid log regex:' — check the exact character/position in the RegExp message
- Escape metacharacters (., *, [, ], (, ), etc.) that should be literal, e.g. \\[' instead of '['
- Test the pattern in isolation: new RegExp(pattern, 'u') in a REPL before passing it to readFiles
- Drop or simplify unicode-specific constructs if the /u flag is the problem (escape lone surrogates as \\u{...} code points)
Example fix
// before
await broker.readFiles({ grep: '[' }); // Invalid log regex: Unterminated character class
// after
await broker.readFiles({ grep: '\\[' }); // matches literal '['
// or validate first:
try { new RegExp(userGrep, 'u'); } catch { userGrep = userGrep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } Defensive patterns
Strategy: validation
Validate before calling
function compileLogGrep(grep: string): RegExp {
try { return new RegExp(grep, 'u'); } catch (e) {
throw new Error(`Invalid log regex: ${e instanceof Error ? e.message : String(e)}`);
}
}
// call compileLogGrep(userGrep) before invoking readFiles Try / catch
try {
await broker.readFiles({ grep: userPattern });
} catch (err) {
if (err instanceof Error && err.message.startsWith('Invalid log regex:')) {
// surface the engine detail to the user and fall back to unfiltered logs
return broker.readFiles({});
}
throw err;
} Prevention
- Validate user-supplied filter patterns with new RegExp(p, 'u') at input time and show inline errors
- Escape metacharacters when the filter is meant to be literal text (escapeRegExp helper)
- Remember the /u flag is always applied: avoid lone surrogates and octal-style escapes
- Unit-test patterns sourced from config or UI free-text fields
When it happens
Trigger: Calling readFiles with grep set to a syntactically invalid pattern, e.g. '[' or 'a{2,1}', or a pattern only invalid with /u like '\\u{}' or a lone surrogate ('\\uD800' unpaired) that the unicode flag rejects.
Common situations: Users typing ad-hoc filter expressions in a UI that are forwarded verbatim to the broker; copying regexes from tools using different flavor syntax (e.g. lookbehind variants, possessive quantifiers) unsupported by the JS engine; forgetting to escape special characters like ( or *; enabling /u semantics inadvertently via this fixed flag.
Related errors
- err.to_string() (invalid regex pattern)
- invalid regular expression: {0}
- Invalid package name: ${name}
- Invalid package name: ${name}
- Daemon name must be 1-48 letters, numbers, dots, underscores
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6aae14aa0c6c1000.
Report an issue: GitHub.