paperclipai/paperclip · error

limit must be a number between 1 and 500

Error message

limit must be a number between 1 and 500

What it means

Returned as HTTP 400 by GET /api/plugins/:pluginId/jobs/:jobId/runs when the optional ?limit= query parameter parses to NaN, is below 1, or above 500. Default is 25 when omitted; any in-range integer 1..500 is accepted.

Source

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

      return;
    }

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

    const job = await jobDeps.jobStore.getJobByIdForPlugin(plugin.id, jobId);
    if (!job) {
      res.status(404).json({ error: "Job not found" });
      return;
    }

    const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 25;
    if (isNaN(limit) || limit < 1 || limit > 500) {
      res.status(400).json({ error: "limit must be a number between 1 and 500" });
      return;
    }

    try {
      const runs = await jobDeps.jobStore.listRunsByJob(jobId, limit);
      res.json(runs);
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      res.status(500).json({ error: message });
    }
  });

  /**
   * POST /api/plugins/:pluginId/jobs/:jobId/trigger
   *
   * Manually trigger a job execution outside its cron schedule.
   *
   * Creates a run with `trigger: "manual"` and dispatches immediately.

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Clamp limit to an integer between 1 and 500 before sending
  2. Omit ?limit to accept the default of 25
  3. Sanitize user-supplied page sizes client-side (Math.min(500, Math.max(1, Math.floor(n))))

Example fix

// before
GET /api/plugins/p/jobs/j/runs?limit=1000
// after
GET /api/plugins/p/jobs/j/runs?limit=100
Defensive patterns

Strategy: validation

Validate before calling

function sanitizeLimit(raw: unknown, fallback = 25): number {
  const n = Math.floor(Number(raw));
  return Number.isFinite(n) ? Math.min(500, Math.max(1, n)) : fallback;
}
const url = `/api/plugins/${pluginId}/jobs/${jobId}/runs?limit=${sanitizeLimit(userLimit)}`;

Try / catch

try { await listJobRuns(pluginId, jobId, limit); } catch (e) { if (e.status === 400 && /limit/.test(e.body.error)) retryWithLimit(25); else throw e; }

Prevention

When it happens

Trigger: Passing ?limit=0, ?limit=-1, ?limit=501, ?limit=abc, or ?limit=1e3. parseInt is used, so '50abc' passes but 'abc' fails; values outside 1..500 are rejected.

Common situations: UI pagination control allowing a page size beyond 500; passing a float like 10.5 (parseInt truncates to 10, which passes) or non-numeric input; copying a limit=1000 default from another endpoint with a higher cap.

Related errors


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