{"record":{"id":"8c6aa38a6b4054d5","repo":"can1357/oh-my-pi","slug":"invalid-package-json-at-absolutepath-err","errorCode":null,"errorMessage":"Invalid package.json at ${absolutePath}: ${err}","messagePattern":"Invalid package\\.json at (.+?): (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/installer.ts","lineNumber":163,"sourceCode":"\n\t// Validate that resolved path is within cwd to prevent path traversal\n\tconst normalizedCwd = path.resolve(cwd);\n\tconst normalizedPath = path.resolve(absolutePath);\n\tif (!normalizedPath.startsWith(`${normalizedCwd}/`) && normalizedPath !== normalizedCwd) {\n\t\tthrow new Error(`Invalid path: ${localPath} resolves outside working directory`);\n\t}\n\n\t// Validate package.json exists\n\tconst pkgFile = Bun.file(path.join(absolutePath, \"package.json\"));\n\tif (!(await pkgFile.exists())) {\n\t\tthrow new Error(`package.json not found at ${absolutePath}`);\n\t}\n\n\tlet pkg: { name?: string };\n\ttry {\n\t\tpkg = await pkgFile.json();\n\t} catch (err) {\n\t\tthrow new Error(`Invalid package.json at ${absolutePath}: ${err}`);\n\t}\n\n\tif (!pkg.name || typeof pkg.name !== \"string\") {\n\t\tthrow new Error(\"package.json must have a valid name field\");\n\t}\n\n\t// Validate package name to prevent path traversal via pkg.name\n\tif (pkg.name.includes(\"..\") || pkg.name.includes(\"/\") || pkg.name.includes(\"\\\\\")) {\n\t\t// Exception: scoped packages have one slash\n\t\tif (!pkg.name.startsWith(\"@\") || (pkg.name.match(/\\//g) || []).length !== 1) {\n\t\t\tthrow new Error(`Invalid package name in package.json: ${pkg.name}`);\n\t\t}\n\t}\n\n\tawait ensurePluginsDir();\n\n\t// Create symlink in plugins/node_modules\n\tconst linkPath = path.join(PLUGINS_DIR, \"node_modules\", pkg.name);","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/installer.ts#L145-L181","documentation":"linkPlugin reads the target package.json with pkgFile.json(). If the file cannot be parsed as JSON the error is rethrown with the path and the original parse error. This wraps JSON syntax errors so the user knows which manifest is broken.","triggerScenarios":"linkPlugin(localPath, cwd) targets a directory whose package.json contains invalid JSON: trailing commas, comments (JSONC), BOM, truncated writes, or non-UTF8 encoding.","commonSituations":"Hand-edited package.json left syntactically invalid; tooling wrote JSONC (comments) which JSON.parse rejects; file partially written during a crash; editor autosave race while the link was attempted.","solutions":["Validate the package.json with `node -e \"JSON.parse(require('fs').readFileSync('<path>/package.json'))\"` or a JSON linter","Fix the reported JSON syntax error (remove trailing commas/comments, fix truncation)","Re-save the file as strict UTF-8 without BOM","Re-run linkPlugin once the file parses"],"exampleFix":"// before: package.json with comment\n{\n\t\"name\": \"my-plugin\", // not valid JSON\n}\n// after\n{\n\t\"name\": \"my-plugin\"\n}","handlingStrategy":"validation","validationCode":"const raw = await Bun.file(path.join(dir, \"package.json\")).text();\nJSON.parse(raw); // throws with position info before calling linkPlugin","typeGuard":null,"tryCatchPattern":"try {\n\tawait linkPlugin(dir);\n} catch (err) {\n\tif (err instanceof Error && err.message.startsWith(\"Invalid package.json\")) {\n\t\tconsole.error(\"Fix JSON syntax in\", err.message.split(\" at \")[1]);\n\t}\n\tthrow err;\n}","preventionTips":["Never put comments or trailing commas in package.json (it is strict JSON, not JSONC)","Run a JSON validator/linter on manifests before linking","Save files as UTF-8 without BOM and confirm writes completed"],"tags":["json-parse","package-json-invalid","plugins","syntax-error"],"backgroundTag":"invalid-json-in-package-json","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}