can1357/oh-my-pi · error · OmpTypeError
unterminated string literal in "${src}"
Error message
unterminated string literal in "${src}" What it means
During tokenization of a type expression, a string literal opened with `'` or `"` reached the end of input without a closing quote (backslash escapes are skipped, but the terminator never appeared). The tokenizer throws rather than treating the rest of the input as the string.
Source
Thrown at packages/omptype/src/ir.ts:215
if (end < 0) throw new OmpTypeError(`unterminated date literal in "${src}"`);
const source = src.slice(i + 2, end).trim();
const value = /^\d+$/.test(source) ? new Date(Number(source)) : new Date(source);
if (Number.isNaN(value.valueOf())) throw new OmpTypeError(`invalid date literal in "${src}"`);
toks.push({ t: "date", v: value });
i = end + 1;
continue;
}
if (c === "'" || c === '"') {
let j = i + 1;
let value = "";
for (; j < n && src[j] !== c; j++) {
if (src[j] === "\\") {
j++;
if (j >= n) break;
}
value += src[j];
}
if (j >= n) throw new OmpTypeError(`unterminated string literal in "${src}"`);
toks.push({ t: "str", v: value });
i = j + 1;
continue;
}
if (c === "/") {
let j = i + 1;
for (; j < n; j++) {
if (src[j] === "\\") j++;
else if (src[j] === "/") break;
}
if (j >= n) throw new OmpTypeError(`unterminated regular expression in "${src}"`);
let end = j + 1;
while (end < n && /[dgimsuvy]/.test(src[end])) end++;
const source = src.slice(i + 1, j);
const flags = src.slice(j + 1, end);
try {
toks.push({ t: "regex", v: new RegExp(source, flags) });
} catch {View on GitHub (pinned to 9690622007)
Solutions
- Add the matching closing quote to the string literal.
- Ensure backslash escapes are doubled when the expression passes through a shell or template layer (`\\` for a literal backslash).
- Avoid a lone trailing backslash immediately before the closing quote.
Example fix
// before type(`name == 'foo`); // after type(`name == 'foo'`);
Defensive patterns
Strategy: validation
Validate before calling
function balancedQuotes(s: string): boolean {
let q: string | null = null;
for (let i = 0; i < s.length; i++) {
if (s[i] === "\\") { i++; continue; }
if (q) { if (s[i] === q) q = null; }
else if (s[i] === "'" || s[i] === '"') q = s[i];
}
return q === null;
} Try / catch
try {
const t = new TypeExpression(src);
} catch (err) {
if (err instanceof Error && err.message.includes("unterminated string literal")) {
throw new Error(`Add closing quote: ${err.message}`);
}
throw err;
} Prevention
- Count quotes before passing expressions built via templating.
- Double backslashes when expressions pass through shells/templates.
- Avoid lone trailing backslashes in literals.
When it happens
Trigger: Expressions like `value == 'abc` or `"unterminated` where the closing quote is missing; escaped quote at the very end consuming the terminator (e.g. `'abc\` with the real closing quote swallowed).
Common situations: Hand-written constraint strings with a dropped quote; quotes stripped by shell escaping or templating engines; trailing backslash before the closing quote.
Related errors
- unterminated date literal in "${src}"
- unterminated regular expression in "${src}"
- No files were modified.
- The first line of the patch must be '*** Begin Patch'
- The last line of the patch must be '*** End Patch'
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/58b42bb0235dfe82.
Report an issue: GitHub.