can1357/oh-my-pi · error · ToolError
Invalid selector ': ' on ' '. Use :N, :N-M, :N+K, :N-…
Error message
Invalid selector ':${internalTarget.sel}' on '${internalTarget.path}'. Use :N, :N-M, :N+K, :N- (open-ended), a comma-separated list of ranges, :raw, :img for SVG rendering, or a range combined w What it means
ReadTool parses a `:selector` suffix attached to a file path or internal URL (line ranges, :raw, :img, etc.). If a selector is present but parseSel cannot classify it into any known form, the tool rejects the whole read with this usage message listing the accepted selector grammar.
Solutions
- Correct the selector to one of the supported forms: :N, :N-M, :N+K, :N- (open-ended), comma-separated ranges, :raw, :img, or :raw:N-M.
- If the path itself contains a colon and no selector is intended, quote or escape the path so the suffix is not parsed as a selector.
- Re-check the exact line numbers/ranges wanted and re-issue the read with a valid comma-separated list (e.g. ':10-20,40').
Example fix
// before
read("src/app.ts:50..60")
// after
read("src/app.ts:50-60") Defensive patterns
Strategy: validation
Validate before calling
const SEL_RE = /^(\d+(-\d+|\+\d+|-)?)(,\d+(-\d+|\+\d+|-)?)*|raw(:\d+-\d+)?|img$/;
if (sel !== undefined && !SEL_RE.test(sel)) throw new Error(`Bad selector ':${sel}'`); Type guard
function isValidSelector(sel) { return sel === undefined || /^(\d+(-\d+|\+\d+|-)?)(,\d+(-\d+|\+\d+|-)?)*$|^raw(:\d+-\d+)?$|^img$/.test(sel); } Try / catch
try { await read(path) } catch (e) { if (e instanceof ToolError && e.message.startsWith('Invalid selector')) { /* retry without selector or fix syntax */ } else throw e; } Prevention
- Only emit selectors matching the documented grammar (:N, :N-M, :N+K, :N-, comma lists, :raw, :img)
- Escape or quote file paths that literally contain colons
- Reuse a shared selector-builder helper instead of string concatenation
When it happens
Trigger: Calling the read tool with a path like 'file.ts:abc', 'dir/:10:11x', or any malformed suffix after a colon on a resolvable internal URL, where splitInternalUrlSel yields a non-empty selector that parseSel returns kind 'none' for.
Common situations: The agent or user hand-writes line selectors and typos them (e.g. ':50-' misspelled as ':50..60', stray text after a valid range), or a filename containing a colon is misinterpreted as carrying a selector.
Related errors
- Cannot combine query extraction with line selectors
- imageSelectorMessage = "The ':img' selector only supports…
- Multi-range line selectors are not supported for directory…
- A postfix required element cannot follow an optional or…
- a user-supplied replacement endpoint is required
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1707e8656d52ebbf.
Report an issue: GitHub.
Appendix: source
Thrown at packages/coding-agent/src/tools/read.ts:1164
});
}
return executeReadUrl(this.session, { path: parsedUrlTarget.path, raw: urlRaw }, signal);
}
// Handle native OMP URLs and custom-scheme resources advertised by MCP servers.
const internalRouter = InternalUrlRouter.instance();
const delimitedInternalResult = internalRouter.canResolve(readPath)
? await this.#tryReadDelimitedPaths(readPath, signal, entry => internalRouter.canResolve(entry))
: null;
if (delimitedInternalResult) return delimitedInternalResult;
// Peel malformed selectors through the internal-URL-aware parser before routing.
let promotedSelector: string | undefined;
if (internalRouter.canResolve(readPath)) {
const internalTarget = splitInternalUrlSel(readPath);
const parsed = parseSel(internalTarget.sel);
if (internalTarget.sel !== undefined && parsed.kind === "none") {
throw new ToolError(
`Invalid selector ':${internalTarget.sel}' on '${internalTarget.path}'. Use :N, :N-M, :N+K, :N- (open-ended), a comma-separated list of ranges, :raw, :img for SVG rendering, or a range combined with raw (e.g. :raw:50-100).`,
);
}
const urlMeta = parseInternalUrl(internalTarget.path);
const scheme = urlMeta.protocol.replace(/:$/, "").toLowerCase();
const imageSelectorMessage = "The ':img' selector only supports local .svg and .svgz files.";
if (parsed.kind === "image" && scheme !== "local") {
throw new ToolError(imageSelectorMessage);
}
if (scheme === "local") {
const localFile = await resolveLocalUrlToFile(urlMeta, {
cwd: this.session.cwd,
settings: this.session.settings,
signal,
localProtocolOptions: this.session.localProtocolOptions,
skills: this.session.skills,
});
if (localFile) {View on GitHub (pinned to 9690622007)