can1357/oh-my-pi · error · Error

line ${lineNum}: expected a line number such as ${describeAn

Error message

line ${lineNum}: expected a line number such as ${describeAnchorExamples("119")}; got ${JSON.stringify(raw)}. Use ${HL_FILE_PREFIX}PATH${HL_FILE_HASH_SEP}hash${HL_FILE_SUFFIX} from your latest read for file-version binding.

What it means

parseLid parses a bare line-number anchor (e.g. "119") in the hashline tokenizer and throws this error when the input is not a well-formed line number (no parsable number, or trailing garbage after the number). It is a fail-fast guard: malformed anchor strings would otherwise silently resolve to the wrong line. The message also reminds the caller that PATH#hash anchors exist for file-version binding.

Source

Thrown at packages/hashline/src/tokenizer.ts:144

	let lineNumber = 0;
	let nextIndex = index;
	while (nextIndex < end) {
		const code = line.charCodeAt(nextIndex);
		if (!isDigitCode(code)) break;
		lineNumber = lineNumber * 10 + (code - CHAR_ZERO);
		if (!Number.isSafeInteger(lineNumber)) return null;
		nextIndex++;
	}
	return { line: lineNumber, nextIndex };
}

/** Parse a bare line-number anchor. Throws on malformed input. */
export function parseLid(raw: string, lineNum: number): Anchor {
	const end = trimEndIndex(raw);
	const numberStart = skipWhitespace(raw, 0, end);
	const number = scanLineNumber(raw, numberStart, end);
	if (number === null || skipWhitespace(raw, number.nextIndex, end) !== end) {
		throw new Error(
			`line ${lineNum}: expected a line number such as ${describeAnchorExamples("119")}; ` +
				`got ${JSON.stringify(raw)}. Use ${HL_FILE_PREFIX}PATH${HL_FILE_HASH_SEP}hash${HL_FILE_SUFFIX} from your latest read for file-version binding.`,
		);
	}
	return { line: number.line };
}

interface RangeScan {
	range: ParsedRange;
	nextIndex: number;
	hadSeparator: boolean;
}

/**
 * Range separator scanner. Canonical input is `.=`, while parsing remains
 * deliberately lenient for model output: `-`, `=`, `.`, `..`, `…`, mixed
 * runs, and whitespace-only separators all recover to the same range.
 */

View on GitHub (pinned to 9690622007)

Solutions

  1. Correct the anchor to a bare integer line number, e.g. "119".
  2. Trim whitespace and remove any trailing annotations from the raw string before calling parseLid.
  3. If you need a file-version-bound reference, use the PATH#hash anchor form (HL_FILE_PREFIX PATH HL_FILE_HASH_SEP hash HL_FILE_SUFFIX) instead of a bare lid.
  4. If you must accept looser formats, sanitize/normalize the input (strip prefixes like 'L', extract the leading integer) before parsing.

Example fix

// before
parseLid("L119", 3) // throws
// after
parseLid("119", 3) // => { line: 119 }
Defensive patterns

Strategy: validation

Validate before calling

const ANCHOR_RE = /^\d+$/;
if (!ANCHOR_RE.test(raw.trim())) throw new Error(`bad lid: ${JSON.stringify(raw)}`);
const anchor = parseLid(raw.trim(), lineNum);

Type guard

function isValidLid(raw: string): boolean {
	const t = raw.trim();
	const n = Number.parseInt(t, 10);
	return Number.isInteger(n) && n > 0 && t === String(n);
}

Try / catch

let anchor;
try {
	anchor = parseLid(raw, lineNum);
} catch (err) {
	throw new UsageError(`Anchor must be a bare line number like '119', got ${raw}`);
}

Prevention

When it happens

Trigger: Calling parseLid with a string like "abc", "12x", "", " ", or "119 #comment" — any raw anchor that fails scanLineNumber or has non-whitespace trailing characters.

Common situations: An LLM or script emits a malformed line reference (e.g. "L119", "119-120", or a range/prefixed form) into an anchor parser; tooling that concatenates a suffix onto the number; copy-pasted anchors with trailing text.

Related errors


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