{"record":{"id":"46a00bdb4d63aa72","repo":"can1357/oh-my-pi","slug":"symbol-symbol-occurrence-occurrence-is-out","errorCode":null,"errorMessage":"Symbol \"${symbol}\" occurrence ${occurrence} is out of bounds on line ${lineNumber} (found ${fallbackIndexes.length})","messagePattern":"Symbol \"(.+?)\" occurrence (.+?) is out of bounds on line (.+?) \\(found (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/lsp/utils.ts","lineNumber":712,"sourceCode":"\nexport async function resolveSymbolColumn(filePath: string, line: number, symbolSpec?: string): Promise<number> {\n\tconst lineNumber = Math.max(1, line);\n\ttry {\n\t\tconst fileText = await Bun.file(filePath).text();\n\t\tconst lines = fileText.split(\"\\n\");\n\t\tconst targetLine = lines[lineNumber - 1] ?? \"\";\n\t\tif (!symbolSpec) {\n\t\t\treturn firstNonWhitespaceColumn(targetLine);\n\t\t}\n\n\t\tconst { symbol, occurrence } = parseSymbolSpec(symbolSpec);\n\t\tconst exactIndexes = findSymbolMatchIndexes(targetLine, symbol);\n\t\tconst fallbackIndexes = exactIndexes.length > 0 ? exactIndexes : findSymbolMatchIndexes(targetLine, symbol, true);\n\t\tif (fallbackIndexes.length === 0) {\n\t\t\tthrow new Error(`Symbol \"${symbol}\" not found on line ${lineNumber}`);\n\t\t}\n\t\tif (occurrence > fallbackIndexes.length) {\n\t\t\tthrow new Error(\n\t\t\t\t`Symbol \"${symbol}\" occurrence ${occurrence} is out of bounds on line ${lineNumber} (found ${fallbackIndexes.length})`,\n\t\t\t);\n\t\t}\n\t\treturn fallbackIndexes[occurrence - 1];\n\t} catch (error) {\n\t\tif (isEnoent(error)) {\n\t\t\tthrow new Error(`File not found: ${filePath}`);\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nexport async function readLocationContext(filePath: string, line: number, contextLines = 1): Promise<string[]> {\n\tconst targetLine = Math.max(1, line);\n\tconst surrounding = Math.max(0, contextLines);\n\ttry {\n\t\tconst fileText = await Bun.file(filePath).text();\n\t\tconst lines = fileText.split(\"\\n\");","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/lsp/utils.ts#L694-L730","documentation":"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.","triggerScenarios":"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.","commonSituations":"Guessing occurrence numbers in agent prompts; the line was edited so a repeated identifier count changed; copying a `#N` spec from a different line.","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."],"exampleFix":"// before\nawait lspTool.execute({ action: \"rename\", file: \"a.ts\", line: 7, symbol: \"x#3\", new_name: \"y\" }); // only 2 x's\n// after\nawait lspTool.execute({ action: \"rename\", file: \"a.ts\", line: 7, symbol: \"x#2\", new_name: \"y\" });","handlingStrategy":"validation","validationCode":"const text = (await Bun.file(file).text()).split(\"\\n\")[line - 1] ?? \"\";\nconst count = text.split(symbolBase).length - 1;\nconst occ = requestedOccurrence && requestedOccurrence <= count ? requestedOccurrence : 1;","typeGuard":null,"tryCatchPattern":"try {\n  return await lspTool.execute({ /* symbol: \"x#3\" */ });\n} catch (err) {\n  const m = err instanceof Error ? err.message.match(/found (\\d+)/) : null;\n  if (m) return lspTool.execute({ /* symbol: `x#${Math.min(3, Number(m[1]))}` */ });\n  throw err;\n}","preventionTips":["Count occurrences on the line before choosing #N.","Default to #1 when ambiguity is acceptable.","Refresh occurrence counts after any edit to the line."],"tags":["lsp","validation","occurrence","parameters"],"backgroundTag":"occurrence-out-of-bounds","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}