{"record":{"id":"e617b52c77bf4ac8","repo":"paperclipai/paperclip","slug":"version-must-be-a-string-if-provided","errorCode":null,"errorMessage":"version must be a string if provided","messagePattern":"version must be a string if provided","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/src/routes/plugins.ts","lineNumber":1153,"sourceCode":"   *\n   * Errors:\n   * - `400` — validation failure or install error (package not found, bad manifest, etc.)\n   * - `403` — install source not permitted on a cloud-managed instance\n   * - `500` — installation succeeded but manifest is missing (indicates a loader bug)\n   */\n  router.post(\"/plugins/install\", async (req, res) => {\n    assertInstanceAdmin(req);\n    assertPluginManagementVisible();\n    const { packageName, version, isLocalPath } = req.body as PluginInstallRequest;\n\n    // Input validation\n    if (!packageName || typeof packageName !== \"string\") {\n      res.status(400).json({ error: \"packageName is required and must be a string\" });\n      return;\n    }\n\n    if (version !== undefined && typeof version !== \"string\") {\n      res.status(400).json({ error: \"version must be a string if provided\" });\n      return;\n    }\n\n    if (isLocalPath !== undefined && typeof isLocalPath !== \"boolean\") {\n      res.status(400).json({ error: \"isLocalPath must be a boolean if provided\" });\n      return;\n    }\n\n    // Validate package name format\n    const trimmedPackage = packageName.trim();\n    if (trimmedPackage.length === 0) {\n      res.status(400).json({ error: \"packageName cannot be empty\" });\n      return;\n    }\n\n    // Basic security check for package name (prevent injection)\n    if (!isLocalPath && /[<>:\"|?*]/.test(trimmedPackage)) {\n      res.status(400).json({ error: \"packageName contains invalid characters\" });","sourceCodeStart":1135,"sourceCodeEnd":1171,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/routes/plugins.ts#L1135-L1171","documentation":"400 validation guard on POST /plugins/install. Fires when a version was supplied in the body but it is not a string (e.g. number); version must be a plain string to be passed to the plugin loader.","triggerScenarios":"Thrown at server/src/routes/plugins.ts:1137 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Fix the offending parameter to satisfy the constraint stated in the error message (type, range, or allowed values), then retry.","Refer to the route's request validation in the named file and the shared validators for the accepted format."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}