santifer/career-ops · error · Error
gmail: invalid days_back
Error message
gmail: invalid days_back "${ctx?.settings?.days_back}" (must be a positive integer) What it means
The Gmail plugin validates the `days_back` setting before building its Gmail search query (`newer_than:{days}d`). It coerces the raw setting with Number() and throws if the result is not a positive integer. This catches non-numeric strings, zero, negatives, and undefined-but-present values so a malformed query is never sent to the Gmail API.
Solutions
- Set days_back to a plain positive integer in the plugin settings, e.g. days_back: 7 (no quotes, no units).
- Remove the days_back key entirely to get the default of 7 days.
- Inspect what the settings loader actually passes — log ctx.settings.days_back and its type; an empty string or 'null' string fails the check.
- If loading config from YAML/JSON, ensure the value is parsed as a number, not left as a string.
Example fix
// before settings: label: Job Leads days_back: "7d" // after settings: label: Job Leads days_back: 7
Defensive patterns
Strategy: validation
Validate before calling
const raw = ctx?.settings?.days_back ?? 7;
const days = Number(raw);
if (!Number.isInteger(days) || days <= 0) {
throw new TypeError(`days_back must be a positive integer, got: ${JSON.stringify(raw)}`);
} Type guard
const isValidDaysBack = (v) => Number.isInteger(Number(v ?? 7)) && Number(v ?? 7) > 0;
Try / catch
try {
await ingest(ctx);
} catch (e) {
if (String(e.message).startsWith('gmail: invalid days_back')) {
ctx.settings.days_back = 7; // fall back to default and retry
await ingest(ctx);
} else throw e;
} Prevention
- Store days_back as a bare number in YAML/JSON (no quotes, no 'd' suffix).
- Omit the key entirely to use the default of 7.
- Validate plugin settings at load time, before the plugin runs.
- Add a schema check (e.g. zod: z.number().int().positive()) in your settings loader.
When it happens
Trigger: Calling the gmail ingest with ctx.settings.days_back set to something that is not a positive integer: a string like '7d' or 'week', 0, a negative number, a float like 1.5, or an empty string. Only an outright undefined/null value is defaulted to 7 — any other bad value throws.
Common situations: Users put `days_back: "last week"` or `days_back: "7d"` (with unit) in their plugin settings YAML; a settings loader passes an empty string; someone copies a config where days_back was left as a placeholder or set to 0 hoping for 'today'.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- apify: entry has invalid field_map. Each of title, url…
- apify: entry missing 'actor' (e.g. misceres/indeed-scraper)
- arbeitnow: invalid URL
- ashby: invalid URL
- bamboohr: invalid URL
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/29821b03df0221ec.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/gmail/index.mjs:83
} catch (err) {
console.warn(`gmail: could not persist processed-id state — ${err.message}`);
}
}
/** @type {{ ingest: (ctx: any) => Promise<object[]> }} */
export default {
async ingest(ctx) {
const clientId = ctx?.env?.GMAIL_CLIENT_ID;
const clientSecret = ctx?.env?.GMAIL_CLIENT_SECRET;
const refreshToken = ctx?.env?.GMAIL_REFRESH_TOKEN;
if (!clientId || !clientSecret || !refreshToken) {
throw new Error('gmail: missing GMAIL_CLIENT_ID / GMAIL_CLIENT_SECRET / GMAIL_REFRESH_TOKEN in .env');
}
const label = ctx?.settings?.label || 'Job Leads';
const daysBack = Number(ctx?.settings?.days_back ?? 7);
if (!Number.isInteger(daysBack) || daysBack <= 0) {
throw new Error(`gmail: invalid days_back "${ctx?.settings?.days_back}" (must be a positive integer)`);
}
const token = await getAccessToken({ clientId, clientSecret, refreshToken }, ctx.fetch);
const auth = { Authorization: `Bearer ${token}` };
const query = `label:"${label}" newer_than:${daysBack}d`;
ctx.log(`gmail: querying ${query}`);
// List message ids (paginated). ctx.fetch throws on a non-2xx (with the body
// in the message), so a failed page surfaces a clear error.
const messages = [];
let pageToken = null;
do {
let url = `${GMAIL_API}/messages?q=${encodeURIComponent(query)}`;
if (pageToken) url += `&pageToken=${pageToken}`;
const data = await (await ctx.fetch(url, { headers: auth })).json();
if (data.messages) messages.push(...data.messages);
pageToken = data.nextPageToken;
} while (pageToken);View on GitHub (pinned to aac998c7ed)