{"record":{"id":"0f25288805d3a7d4","repo":"can1357/oh-my-pi","slug":"package-json-must-have-a-name-field","errorCode":null,"errorMessage":"package.json must have a name field","messagePattern":"package\\.json must have a name field","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/manager.ts","lineNumber":783,"sourceCode":"\t\treturn plugins;\n\t}\n\n\t/**\n\t * Link a local plugin for development.\n\t */\n\tasync link(localPath: string): Promise<InstalledPlugin> {\n\t\tconst absolutePath = path.resolve(this.#cwd, localPath);\n\n\t\tconst pkgFilePath = path.join(absolutePath, \"package.json\");\n\t\tlet pkg: { name?: string; version: string; omp?: PluginManifest; pi?: PluginManifest };\n\t\ttry {\n\t\t\tpkg = await Bun.file(pkgFilePath).json();\n\t\t} catch (err) {\n\t\t\tif (isEnoent(err)) throw new Error(`package.json not found at ${absolutePath}`);\n\t\t\tthrow err;\n\t\t}\n\t\tif (!pkg.name) {\n\t\t\tthrow new Error(\"package.json must have a name field\");\n\t\t}\n\n\t\tawait this.#ensurePluginsDir();\n\n\t\tconst linkPath = path.join(getPluginsNodeModules(), pkg.name);\n\n\t\t// Handle scoped packages\n\t\tif (pkg.name.startsWith(\"@\")) {\n\t\t\tconst scopeDir = path.join(getPluginsNodeModules(), pkg.name.split(\"/\")[0]);\n\t\t\tawait fs.promises.mkdir(scopeDir, { recursive: true });\n\t\t}\n\n\t\t// Remove existing\n\t\ttry {\n\t\t\tconst stats = await fs.promises.lstat(linkPath);\n\t\t\tif (stats.isSymbolicLink() || stats.isDirectory()) {\n\t\t\t\tawait fs.promises.unlink(linkPath);\n\t\t\t}","sourceCodeStart":765,"sourceCodeEnd":801,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/manager.ts#L765-L801","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (package.json)\n{ \"version\": \"1.0.0\", \"omp\": { \"features\": {} } }\n// after\n{ \"name\": \"my-plugin\", \"version\": \"1.0.0\", \"omp\": { \"features\": {} } }","handlingStrategy":"validation","validationCode":"const pkg = await Bun.file(path.join(pluginDir, \"package.json\")).json();\nif (typeof pkg.name !== \"string\" || pkg.name.length === 0) {\n  throw new Error(`${pluginDir}/package.json has no name`);\n}","typeGuard":"function isNamedPackage(pkg: unknown): pkg is { name: string; version: string } {\n  return typeof pkg === \"object\" && pkg !== null &&\n    typeof (pkg as { name?: unknown }).name === \"string\" &&\n    (pkg as { name: string }).name.length > 0;\n}","tryCatchPattern":"try {\n  await manager.installFromPath(dir);\n} catch (err) {\n  if (err instanceof Error && err.message === \"package.json must have a name field\") {\n    console.error(\"Add a non-empty name to the plugin package.json\");\n  } else throw err;\n}","preventionTips":["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"],"tags":["plugins","validation","package-json","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}