{"record":{"id":"b98b740e0f07b52d","repo":"can1357/oh-my-pi","slug":"multi-range-line-selectors-are-not-supported-for-d","errorCode":null,"errorMessage":"Multi-range line selectors are not supported for directory listings.","messagePattern":"Multi-range line selectors are not supported for directory listings\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/read.ts","lineNumber":1314,"sourceCode":"\t\t\t\t\t\t\t// The referenced plan disappeared after resolution; continue through\n\t\t\t\t\t\t\t// the ordinary delimited-path fallback and not-found error.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!recoveredApprovedPlan && !suffixResolution) {\n\t\t\t\t\tconst delimitedResult = await this.#tryReadDelimitedPaths(readPath, signal);\n\t\t\t\t\tif (delimitedResult) return delimitedResult;\n\t\t\t\t\tthrow new ToolError(`Path '${localReadPath}' not found`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tif (isDirectory) {\n\t\t\tif (isMultiRange(parsed)) {\n\t\t\t\tthrow new ToolError(\"Multi-range line selectors are not supported for directory listings.\");\n\t\t\t}\n\t\t\tconst { offset, limit } = selToOffsetLimit(parsed);\n\t\t\t// Directory listings are deterministic and fast; never abort them mid-scan\n\t\t\t// (an interrupt would otherwise surface a misleading \"Operation aborted\").\n\t\t\tconst dirResult = await this.#readDirectory(absolutePath, offset, limit, undefined);\n\t\t\tif (suffixResolution) {\n\t\t\t\tdirResult.details ??= {};\n\t\t\t\tdirResult.details.suffixResolution = suffixResolution;\n\t\t\t}\n\t\t\treturn dirResult;\n\t\t}\n\n\t\tif (parsed.kind === \"conflicts\") {\n\t\t\treturn this.#readFileConflicts(absolutePath, suffixResolution, signal);\n\t\t}\n\n\t\tif (pdfImageRead) {\n\t\t\treturn this.#readPdfPageScreenshot({","sourceCodeStart":1296,"sourceCodeEnd":1332,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/read.ts#L1296-L1332","documentation":"Directory listings accept a single offset/limit window derived from the selector, so a comma-separated multi-range selector (isMultiRange) cannot be applied. ReadTool rejects the combination up front.","triggerScenarios":"Reading a directory path with a multi-range selector such as 'src/:1-10,20-30' — the directory branch throws before #readDirectory runs.","commonSituations":"Reusing a multi-range selector that worked on a file against a directory; agent constructs a combined listing window across disjoint ranges of a tree listing.","solutions":["Use a single range or open-ended selector on the directory (e.g. ':1-20' or ':10-').","Issue multiple directory reads, one per range, and merge results yourself.","Drop the selector to get the full listing and slice locally."],"exampleFix":"// before\nread(\"src/:1-10,50-60\")\n// after\nread(\"src/:1-10\")  // repeat with :50-60 if needed","handlingStrategy":"validation","validationCode":"const ranges = sel.split(','); if (isDir && ranges.length > 1) throw new Error('Use a single range for directory reads');","typeGuard":"function isMultiRangeSel(sel) { return typeof sel === 'string' && sel.includes(','); }","tryCatchPattern":"try { return await read(dir + ':' + sel) } catch (e) { if (String(e.message).includes('Multi-range')) { return await read(dir + ':' + sel.split(',')[0]); } throw e; }","preventionTips":["Use single ranges or open-ended selectors on directories","Fan out multiple reads for disjoint ranges","Slice full listings client-side instead of multi-range selectors"],"tags":["read-tool","directory","selector-syntax"],"backgroundTag":"unsupported-selector-combination","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}