paperclipai/paperclip · error

Invalid status '${rawStatus}'. Must be one of: ${validStatus

Error message

Invalid status '${rawStatus}'. Must be one of: ${validStatuses.join(", ")}

What it means

Returned as HTTP 400 by GET /api/plugins/:pluginId/jobs when the optional ?status= query filter is present but not one of the allowed values active, paused, failed. The message lists the accepted values verbatim.

Source

Thrown at server/src/routes/plugins.ts:2558

   */
  router.get("/plugins/:pluginId/jobs", async (req, res) => {
    assertBoardOrgAccess(req);
    if (!jobDeps) {
      res.status(501).json({ error: "Job scheduling is not enabled" });
      return;
    }

    const { pluginId } = req.params;
    const plugin = await resolvePlugin(registry, pluginId);
    if (!plugin) {
      res.status(404).json({ error: "Plugin not found" });
      return;
    }

    const rawStatus = req.query.status as string | undefined;
    const validStatuses = ["active", "paused", "failed"];
    if (rawStatus !== undefined && !validStatuses.includes(rawStatus)) {
      res.status(400).json({
        error: `Invalid status '${rawStatus}'. Must be one of: ${validStatuses.join(", ")}`,
      });
      return;
    }

    try {
      const jobs = await jobDeps.jobStore.listJobs(
        plugin.id,
        rawStatus as "active" | "paused" | "failed" | undefined,
      );
      res.json(jobs);
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      res.status(500).json({ error: message });
    }
  });

  /**

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Use exactly one of: active, paused, failed
  2. Omit ?status entirely to list all jobs
  3. Fix the client-side enum that feeds the filter to the three supported values

Example fix

// before
GET /api/plugins/scheduler/jobs?status=running
// after
GET /api/plugins/scheduler/jobs?status=active
Defensive patterns

Strategy: validation

Validate before calling

const JOB_STATUSES = ['active', 'paused', 'failed'] as const;
type JobStatus = typeof JOB_STATUSES[number];
function isJobStatus(v: string): v is JobStatus { return (JOB_STATUSES as readonly string[]).includes(v); }
if (status !== undefined && !isJobStatus(status)) throw new Error(`status must be one of: ${JOB_STATUSES.join(', ')}`);

Type guard

const JOB_STATUSES = ['active', 'paused', 'failed'] as const;
type JobStatus = typeof JOB_STATUSES[number];
function isJobStatus(v: string): v is JobStatus {
  return (JOB_STATUSES as readonly string[]).includes(v);
}

Try / catch

try { await listPluginJobs(pluginId, status); } catch (e) { if (e.status === 400 && /Invalid status/.test(e.body.error)) fallbackToAllJobs(); else throw e; }

Prevention

When it happens

Trigger: Passing ?status=running, ?status=succeeded, ?status=completed, or any free-text value; passing multiple comma-joined statuses like active,paused.

Common situations: Assuming job statuses mirror run statuses (e.g. 'succeeded'); copying status vocabulary from another API; UI dropdown fed from the wrong enum source.

Related errors


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18). Data as JSON: /api/errors/8b560400102e56b0. Report an issue: GitHub.