can1357/oh-my-pi · error · ToolError
URL selector has multiple range groups; combine them with co
Error message
URL selector has multiple range groups; combine them with commas (e.g. `:5-10,20-30`).
What it means
parseReadUrlTarget parses URL#selector suffixes for the fetch/read-URL tool. Line-range selectors are given as a single group like `:5-10` and multiple groups must be comma-joined (`:5-10,20-30`). If a second colon-separated range group appears (`url:5-10:20-30`) while one was already parsed, the parser throws this guidance error instead of silently misreading the target.
Source
Thrown at packages/coding-agent/src/tools/fetch.ts:189
export function parseReadUrlTarget(readPath: string): ParsedReadUrlTarget | null {
const repaired = repairCollapsedScheme(readPath);
const embedded = tryExtractEmbeddedUrlSelector(repaired);
const urlPath = embedded?.path ?? repaired;
if (!isReadableUrlPath(urlPath)) {
return null;
}
let raw = false;
let ranges: readonly LineRange[] | undefined;
for (const sel of embedded?.sels ?? []) {
if (sel.toLowerCase() === "raw") {
raw = true;
continue;
}
if (ranges !== undefined) {
// Two range groups on the same URL (`…:5-10:20-30`) — combine with commas instead.
throw new ToolError(
`URL selector has multiple range groups; combine them with commas (e.g. \`:5-10,20-30\`).`,
);
}
const parsed = parseLineRanges(sel);
if (parsed === null) {
// Shouldn't happen — isUrlSelectorToken vetted it. Belt-and-suspenders.
throw new ToolError(`Invalid URL line selector: ${sel}`);
}
ranges = parsed;
}
if (!ranges || ranges.length === 0) return { path: urlPath, raw };
if (ranges.length === 1) {
const r = ranges[0];
return {
path: urlPath,
raw,
offset: r.startLine,View on GitHub (pinned to 9690622007)
Solutions
- Merge the ranges into one comma-separated selector: `url:5-10,20-30`.
- Issue two separate read calls with one range each if comma syntax is not supported by your caller.
- If raw content plus a range is needed, keep the `raw` token and one comma-joined range group.
Example fix
// before "https://example.com/data.txt:1-5:10-20" // after "https://example.com/data.txt:1-5,10-20"
Defensive patterns
Strategy: validation
Validate before calling
const m = url.match(/:([0-9,-]+(?:,[0-9,-]+)*)$/);
if (url.includes(":") && /:[0-9]+-[0-9]+:[0-9]/.test(url)) {
url = url.replace(/:([0-9-]+):([0-9,-]+)/, ":$1,$2");
} Type guard
function hasSingleRangeGroup(url: string): boolean { const parts = url.split(":"); const sel = parts.slice(2).join(":"); return !sel.split(":").every(p => /^raw$|^[0-9,-]+$/.test(p)) || sel.split(":").filter(p => /^[0-9,-]+$/.test(p)).length <= 1; } Try / catch
try {
await fetchTool.readUrl(id, { url: target }, signal);
} catch (e) {
if (e instanceof ToolError && e.message.includes("multiple range groups")) {
// normalize selector to comma form and retry once
} else throw e;
} Prevention
- Always comma-join multiple line ranges: `:5-10,20-30`.
- Validate selector syntax before building tool arguments.
- Restrict generated URLs to a single range group per call.
When it happens
Trigger: Calling the fetch/read-URL tool with a URL target containing two colon-delimited range groups, e.g. `https://example.com/file.txt:1-5:10-20`.
Common situations: Users familiar with other tools' `start:end` colon syntax chaining ranges with extra colons; model-generated tool arguments guessing at multi-range syntax.
Related errors
- Invalid URL line selector: ${sel}
- Discord webhook credential is not a valid URL
- Discord webhook credential does not contain a webhook ID and
- Discord attachment URL is invalid
- ${destination} returned an invalid image URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/4258edba0a92e75f.
Report an issue: GitHub.