can1357/oh-my-pi · error · Error
package.json must have a name field
Error message
package.json must have a name field
What it means
After successfully reading package.json, PluginManager requires a non-empty "name" field because the name is used to compute the node_modules link path (getPluginsNodeModules()/pkg.name) and as the plugin's registry key. A package.json without a name (or with an empty one) is rejected before any linking happens.
Source
Thrown at packages/coding-agent/src/extensibility/plugins/manager.ts:783
return plugins;
}
/**
* Link a local plugin for development.
*/
async link(localPath: string): Promise<InstalledPlugin> {
const absolutePath = path.resolve(this.#cwd, localPath);
const pkgFilePath = path.join(absolutePath, "package.json");
let pkg: { name?: string; version: string; omp?: PluginManifest; pi?: PluginManifest };
try {
pkg = await Bun.file(pkgFilePath).json();
} catch (err) {
if (isEnoent(err)) throw new Error(`package.json not found at ${absolutePath}`);
throw err;
}
if (!pkg.name) {
throw new Error("package.json must have a name field");
}
await this.#ensurePluginsDir();
const linkPath = path.join(getPluginsNodeModules(), pkg.name);
// Handle scoped packages
if (pkg.name.startsWith("@")) {
const scopeDir = path.join(getPluginsNodeModules(), pkg.name.split("/")[0]);
await fs.promises.mkdir(scopeDir, { recursive: true });
}
// Remove existing
try {
const stats = await fs.promises.lstat(linkPath);
if (stats.isSymbolicLink() || stats.isDirectory()) {
await fs.promises.unlink(linkPath);
}View on GitHub (pinned to 9690622007)
Solutions
- Add a "name" field to the plugin's package.json (lowercase, npm-valid).
- Ensure the name is non-empty and unique among installed plugins.
- Regenerate the package.json with a proper scaffolding tool if it was hand-written.
- If the file is not meant to be a plugin package, move the omp/pi manifest to the correct plugin descriptor file.
Example fix
// before (package.json)
{ "version": "1.0.0", "omp": { "features": {} } }
// after
{ "name": "my-plugin", "version": "1.0.0", "omp": { "features": {} } } Defensive patterns
Strategy: validation
Validate before calling
const pkg = await Bun.file(path.join(pluginDir, "package.json")).json();
if (typeof pkg.name !== "string" || pkg.name.length === 0) {
throw new Error(`${pluginDir}/package.json has no name`);
} Type guard
function isNamedPackage(pkg: unknown): pkg is { name: string; version: string } {
return typeof pkg === "object" && pkg !== null &&
typeof (pkg as { name?: unknown }).name === "string" &&
(pkg as { name: string }).name.length > 0;
} Try / catch
try {
await manager.installFromPath(dir);
} catch (err) {
if (err instanceof Error && err.message === "package.json must have a name field") {
console.error("Add a non-empty name to the plugin package.json");
} else throw err;
} Prevention
- Always include name and version in plugin package.json
- Lint plugin packages with npm pkg get name before distribution
- Use a plugin scaffold/template that emits a complete package.json
- Never hand-write minimal package.json files for plugins
When it happens
Trigger: Installing a plugin whose package.json omits the "name" field or has "name": ""; loading a hand-written or generated package.json used only as a manifest container.
Common situations: Minimal/hand-rolled package.json missing name; a JSON file that parses but is not a real npm package; scripts generating package.json that skip the name field.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- anthropic-messages: ${data.summary}
- Schema contains a circular object graph — cannot enforce str
- Schema node has no type, combinator, or $ref — cannot enforc
- Validation failed for tool "${toolCall.name}":\n${errors}\n\
- ClinePass model catalog response is missing clinePass
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/0f25288805d3a7d4.
Report an issue: GitHub.