can1357/oh-my-pi · error
Symbol "${symbol}" occurrence ${occurrence} is out of bounds
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.
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)
Solutions
- Lower the occurrence number to one that exists (the error states the found count, e.g. found 2 → use #1 or #2).
- Re-read the line to count occurrences before specifying `#N`.
- 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
- Count occurrences on the line before choosing #N.
- Default to #1 when ambiguity is acceptable.
- Refresh occurrence counts after any edit to the line.
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
- symbol is required for project-aware ${action}; pass symbol=
- Symbol "${symbol}" not found on line ${lineNumber}
- File not found: ${filePath}
- Report cannot be empty.
- Limit must be a positive number
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/46a00bdb4d63aa72.
Report an issue: GitHub.