{"record":{"id":"c98e0ed0bde18d2d","repo":"paperclipai/paperclip","slug":"job-scheduling-is-not-enabled","errorCode":null,"errorMessage":"Job scheduling is not enabled","messagePattern":"Job scheduling is not enabled","errorType":"http","errorClass":null,"httpStatus":501,"severity":"error","filePath":"server/src/routes/plugins.ts","lineNumber":2544,"sourceCode":"  // ===========================================================================\n  // Job scheduling routes\n  // ===========================================================================\n\n  /**\n   * GET /api/plugins/:pluginId/jobs\n   *\n   * List all scheduled jobs for a plugin.\n   *\n   * Query params:\n   * - `status` (optional): Filter by job status (`active`, `paused`, `failed`)\n   *\n   * Response: PluginJobRecord[]\n   * Errors: 404 if plugin not found\n   */\n  router.get(\"/plugins/:pluginId/jobs\", async (req, res) => {\n    assertBoardOrgAccess(req);\n    if (!jobDeps) {\n      res.status(501).json({ error: \"Job scheduling is not enabled\" });\n      return;\n    }\n\n    const { pluginId } = req.params;\n    const plugin = await resolvePlugin(registry, pluginId);\n    if (!plugin) {\n      res.status(404).json({ error: \"Plugin not found\" });\n      return;\n    }\n\n    const rawStatus = req.query.status as string | undefined;\n    const validStatuses = [\"active\", \"paused\", \"failed\"];\n    if (rawStatus !== undefined && !validStatuses.includes(rawStatus)) {\n      res.status(400).json({\n        error: `Invalid status '${rawStatus}'. Must be one of: ${validStatuses.join(\", \")}`,\n      });\n      return;\n    }","sourceCodeStart":2526,"sourceCodeEnd":2562,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/routes/plugins.ts#L2526-L2562","documentation":"Returned as HTTP 501 by GET /api/plugins/:pluginId/jobs when the server was constructed without job scheduling dependencies (jobDeps is undefined). All job routes — list, runs, trigger — uniformly refuse with this error when the scheduler/job store is not wired into the API.","triggerScenarios":"Calling GET /api/plugins/:pluginId/jobs (optionally ?status=...) on a deployment where the job scheduling subsystem was not enabled at boot.","commonSituations":"Minimal or older self-hosted builds without the scheduler; feature disabled by configuration; UI shows a jobs tab but the backing server lacks the job subsystem.","solutions":["Enable job scheduling (jobDeps wiring) in the server configuration for that deployment","Confirm the deployment version supports scheduled plugin jobs","Until enabled, hide the jobs UI affordance so users do not hit the 501"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// One-time capability probe, cached\nlet jobsEnabled: boolean | null = null;\nasync function checkJobsEnabled() {\n  if (jobsEnabled === null) {\n    const r = await fetch(`/api/plugins/${pluginId}/jobs`);\n    jobsEnabled = r.status !== 501;\n  }\n  return jobsEnabled;\n}","typeGuard":null,"tryCatchPattern":"try { return await listPluginJobs(pluginId); } catch (e) { if (e.status === 501) return { jobs: [], schedulingDisabled: true }; throw e; }","preventionTips":["Hide the jobs tab when the server reports 501 instead of surfacing an error","Cache the capability result per server instance","Do not retry 501 responses; they are deterministic"],"tags":["http-501","plugins","job-scheduling","feature-disabled"],"backgroundTag":"feature-not-enabled","analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}