can1357/oh-my-pi · error · OmpTypeError

unexpected character '${c}' in "${src}"

Error message

unexpected character '${c}' in "${src}"

What it means

The tokenizer hit a character that cannot start any token in an omptype string definition. Only digits, letters/_/$, quotes, '/', and known operators (SIMPLE_OPS, <, <=, >, >=, ==) are recognized; anything else (e.g. '@', '!', ';', ':', unicode punctuation) is rejected so that typos fail loudly instead of producing a mis-parsed schema.

Source

Thrown at packages/omptype/src/ir.ts:281

				toks.push({ t: "op", v: `${c}=` });
				i += 2;
			} else {
				toks.push({ t: "op", v: c });
				i++;
			}
			continue;
		}
		if (c === "=" && src[i + 1] === "=") {
			toks.push({ t: "op", v: "==" });
			i += 2;
			continue;
		}
		if (SIMPLE_OPS.includes(c)) {
			toks.push({ t: "op", v: c });
			i++;
			continue;
		}
		throw new OmpTypeError(`unexpected character '${c}' in "${src}"`);
	}
	return toks;
}

// ── string-definition parser ─────────────────────────────────────────────────

const CMP: Record<string, true> = { "<": true, "<=": true, ">": true, ">=": true };

const KEYWORDS: Record<string, () => IR> = {
	number: () => ({ k: "number" }),
	"number.integer": () => ({ k: "number", int: true }),
	boolean: () => ({ k: "boolean" }),
	bigint: () => ({ k: "bigint" }),
	symbol: () => ({ k: "symbol" }),
	never: () => ({ k: "never" }),
	null: () => ({ k: "null" }),
	undefined: () => ({ k: "undefined" }),
	unknown: () => ({ k: "unknown" }),

View on GitHub (pinned to 9690622007)

Solutions

  1. Find the reported character in the echoed source string and remove or replace it with valid omptype syntax.
  2. Replace smart quotes/unicode punctuation with ASCII equivalents (' instead of ').
  3. Use '|' for unions and '&' for intersections instead of TS-style characters; consult the supported operator set (| & ( ) [ ] # % < <= > >= == = ? ,).
  4. If the string is built dynamically, sanitize/validate the interpolated fragment before composing the definition.

Example fix

// before
schema.parse("string@");
// after
schema.parse("string"); // or "string.email" etc.
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = /^[\w$.'"\/\s|&()\[\]#%<>=?,+\-:]/; // reject unknown chars up front
if (/[“”‘’]/.test(def)) throw new Error("smart quotes in definition");

Try / catch

try {
  const schema = parse(def);
} catch (e) {
  if (String(e.message).includes("unexpected character")) {
    // strip/replace the offending char and retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: Any parse of a string definition containing an unsupported character: 'string@', 'number!', 'string; number', stray quotes/braces outside their grammar, or smart quotes ('“string”') pasted from docs.

Common situations: Copy-pasting type expressions from blogs/docs that contain smart quotes or non-ASCII dashes; typos like 'number!!'; using characters from a different type syntax (e.g. ':' or '=>' from TS); shell quoting mangling definition strings.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/3e1063c0b8f8a8d2. Report an issue: GitHub.