can1357/oh-my-pi · error · ToolError
path must be repository-relative
Error message
path must be repository-relative
What it means
executeFileRead reads a file's contents from a GitHub repository via the gh-backed API. The `path` parameter must be relative to the repository root; an absolute path (leading '/') would produce a malformed API path, so it is rejected up front with a ToolError.
Source
Thrown at packages/coding-agent/src/tools/gh.ts:267
return executeSearchCommits(this.session, params, signal);
case "search_repos":
return executeSearchRepos(this.session, params, signal);
case "run_watch":
return executeRunWatch(this.session, this.name, params, signal, onUpdate);
}
});
}
}
async function executeFileRead(
session: ToolSession,
params: GithubInput,
signal: AbortSignal | undefined,
): Promise<AgentToolResult<GhToolDetails>> {
const repo = await resolveGitHubRepo(session.cwd, normalizeOptionalString(params.repo), undefined, signal);
const filePath = requireNonEmpty(normalizeOptionalString(params.path), "path");
if (filePath.startsWith("/")) {
throw new ToolError("path must be repository-relative");
}
const branch = normalizeOptionalString(params.branch);
const endpointPath = filePath
.split("/")
.map(segment => encodeURIComponent(segment))
.join("/");
const ref = parseRepoRef(repo);
const args = [
"api",
...ghApiHostArgs(ref),
`/repos/${ref.slug}/contents/${endpointPath}`,
"--method",
"GET",
"-H",
"Accept: application/vnd.github+json",
"-H",
"Accept-Encoding: identity",
];View on GitHub (pinned to 9690622007)
Solutions
- Remove the leading slash: 'src/index.ts' instead of '/src/index.ts'
- Strip the repo-root prefix if the input came from a local absolute path
- Normalize with something like path.replace(/^\/+/, '') before invoking
Example fix
// before
await executeFileRead({ path: "/src/index.ts" });
// after
await executeFileRead({ path: "src/index.ts" }); Defensive patterns
Strategy: validation
Validate before calling
const rel = normalizeOptionalString(params.path)?.replace(/^\\/+/, "");
if (!rel) throw new Error("path required");
await executeFileRead({ ...params, path: rel }); Type guard
const isRepoRelativePath = (p: string): boolean => p.length > 0 && !p.startsWith("/"); Try / catch
try {
await gh.readFile({ path });
} catch (err) {
if (err instanceof ToolError && err.message === "path must be repository-relative") {
path = path.replace(/^\\/+/, "");
// retry once with the corrected path
} else throw err;
} Prevention
- Normalize paths with .replace(/^\\/+/, '') at the boundary
- Never pass local absolute paths directly as GitHub paths
- Strip URL path prefixes when deriving the repo path from a URL
When it happens
Trigger: Calling the github file-read op with path: '/src/index.ts' or path: '/README.md' — any string whose first character is '/'.
Common situations: Agents converting local absolute paths directly to GitHub paths; users pasting URLs where the leading slash of the path segment survived; code that does path.join('/', file).
Related errors
- Not a file: ${shortenPath(resolved)}
- invalid issue identifier: ${identifier}. Pass an issue numbe
- GitHub path '${filePath}' is not a file.
- Searching from root directory '/' is not allowed
- `path` must contain non-empty globs or paths
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/95a0c6369d45f39c.
Report an issue: GitHub.