can1357/oh-my-pi · error · Error
package.json not found at ${absolutePath}
Error message
package.json not found at ${absolutePath} What it means
After the path-traversal check, linkPlugin verifies that a package.json exists in the target directory before reading it. This error is thrown when the resolved absolutePath exists but does not contain a package.json, so it cannot be treated as a linkable package.
Source
Thrown at packages/coding-agent/src/extensibility/plugins/installer.ts:156
return plugins;
}
export async function linkPlugin(localPath: string): Promise<void> {
const cwd = getProjectDir();
const absolutePath = path.resolve(cwd, localPath);
// Validate that resolved path is within cwd to prevent path traversal
const normalizedCwd = path.resolve(cwd);
const normalizedPath = path.resolve(absolutePath);
if (!normalizedPath.startsWith(`${normalizedCwd}/`) && normalizedPath !== normalizedCwd) {
throw new Error(`Invalid path: ${localPath} resolves outside working directory`);
}
// Validate package.json exists
const pkgFile = Bun.file(path.join(absolutePath, "package.json"));
if (!(await pkgFile.exists())) {
throw new Error(`package.json not found at ${absolutePath}`);
}
let pkg: { name?: string };
try {
pkg = await pkgFile.json();
} catch (err) {
throw new Error(`Invalid package.json at ${absolutePath}: ${err}`);
}
if (!pkg.name || typeof pkg.name !== "string") {
throw new Error("package.json must have a valid name field");
}
// Validate package name to prevent path traversal via pkg.name
if (pkg.name.includes("..") || pkg.name.includes("/") || pkg.name.includes("\\")) {
// Exception: scoped packages have one slash
if (!pkg.name.startsWith("@") || (pkg.name.match(/\//g) || []).length !== 1) {
throw new Error(`Invalid package name in package.json: ${pkg.name}`);View on GitHub (pinned to 9690622007)
Solutions
- Point localPath at the directory containing package.json, not a parent or subdir
- Run `npm init -y` (or create package.json manually with a name field) in the target folder
- Verify with ls that package.json exists at the resolved path before calling linkPlugin
- Check the directory was fully cloned/copied and package.json was not excluded
Example fix
// before
await linkPlugin("./my-plugin/src");
// after
await linkPlugin("./my-plugin"); Defensive patterns
Strategy: validation
Validate before calling
const abs = path.resolve(cwd, localPath);
const stat = await Bun.file(path.join(abs, "package.json")).exists();
if (!stat) throw new Error(`${abs} is not a package root`); Try / catch
try {
await linkPlugin(localPath);
} catch (err) {
if (err instanceof Error && err.message.startsWith("package.json not found")) {
// point at the package root or scaffold a package.json
}
throw err;
} Prevention
- Always link the folder that directly contains package.json
- Scaffold new plugins with a package.json before linking (`npm init -y`)
- Verify directory contents when cloning partial/copy-filtered repos
When it happens
Trigger: linkPlugin(localPath, cwd) points at a directory that is not a package root: an empty folder, a source subdirectory (e.g. src/) rather than the package root, a typo'd folder name, or a repo checked out without its package.json.
Common situations: Linking the repo root of a monorepo instead of the specific package folder; creating the plugin directory but not running `npm init`/writing package.json yet; .gitignore or checkout rules excluding package.json.
Related errors
- Package installed but package.json not found at ${pkgPath}
- package.json not found at ${absolutePath}
- unknown filetype: {ft_debug}
- Is a directory
- Too many levels of symbolic links
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6c62a1b56a0de8f5.
Report an issue: GitHub.