can1357/oh-my-pi · error

Symbol " " occurrence is out of bounds on line (found )

Error message

Symbol "${symbol}" occurrence ${occurrence} is out of bounds on line ${lineNumber} (found ${fallbackIndexes.length})

What it means

After matching the requested symbol on the line, resolveSymbolColumn indexes into the match list with the 1-based occurrence from the `symbol#N` spec. If N exceeds the number of matches found (exact or fallback), this error reports how many occurrences actually exist.

Solutions

  1. Lower the occurrence number to one that exists (the error states the found count, e.g. found 2 → use #1 or #2).
  2. Re-read the line to count occurrences before specifying `#N`.
  3. Omit `#N` to use the first occurrence when ambiguity doesn't matter.

Example fix

// before
await lspTool.execute({ action: "rename", file: "a.ts", line: 7, symbol: "x#3", new_name: "y" }); // only 2 x's
// after
await lspTool.execute({ action: "rename", file: "a.ts", line: 7, symbol: "x#2", new_name: "y" });
Defensive patterns

Strategy: validation

Validate before calling

const text = (await Bun.file(file).text()).split("\n")[line - 1] ?? "";
const count = text.split(symbolBase).length - 1;
const occ = requestedOccurrence && requestedOccurrence <= count ? requestedOccurrence : 1;

Try / catch

try {
  return await lspTool.execute({ /* symbol: "x#3" */ });
} catch (err) {
  const m = err instanceof Error ? err.message.match(/found (\d+)/) : null;
  if (m) return lspTool.execute({ /* symbol: `x#${Math.min(3, Number(m[1]))}` */ });
  throw err;
}

Prevention

When it happens

Trigger: Passing `symbol=myFunc#3` when the target line contains fewer than 3 occurrences of `myFunc` — execute() → resolveSymbolColumn → parseSymbolSpec gives occurrence=3 but fallbackIndexes.length < 3.

Common situations: Guessing occurrence numbers in agent prompts; the line was edited so a repeated identifier count changed; copying a `#N` spec from a different line.

Related errors


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

Appendix: source

Thrown at packages/coding-agent/src/lsp/utils.ts:712

export async function resolveSymbolColumn(filePath: string, line: number, symbolSpec?: string): Promise<number> {
	const lineNumber = Math.max(1, line);
	try {
		const fileText = await Bun.file(filePath).text();
		const lines = fileText.split("\n");
		const targetLine = lines[lineNumber - 1] ?? "";
		if (!symbolSpec) {
			return firstNonWhitespaceColumn(targetLine);
		}

		const { symbol, occurrence } = parseSymbolSpec(symbolSpec);
		const exactIndexes = findSymbolMatchIndexes(targetLine, symbol);
		const fallbackIndexes = exactIndexes.length > 0 ? exactIndexes : findSymbolMatchIndexes(targetLine, symbol, true);
		if (fallbackIndexes.length === 0) {
			throw new Error(`Symbol "${symbol}" not found on line ${lineNumber}`);
		}
		if (occurrence > fallbackIndexes.length) {
			throw new Error(
				`Symbol "${symbol}" occurrence ${occurrence} is out of bounds on line ${lineNumber} (found ${fallbackIndexes.length})`,
			);
		}
		return fallbackIndexes[occurrence - 1];
	} catch (error) {
		if (isEnoent(error)) {
			throw new Error(`File not found: ${filePath}`);
		}
		throw error;
	}
}

export async function readLocationContext(filePath: string, line: number, contextLines = 1): Promise<string[]> {
	const targetLine = Math.max(1, line);
	const surrounding = Math.max(0, contextLines);
	try {
		const fileText = await Bun.file(filePath).text();
		const lines = fileText.split("\n");

View on GitHub (pinned to 9690622007)