{"record":{"id":"3262c0e7e2bbf958","repo":"santifer/career-ops","slug":"apify-invalid-timeoutms-json-stringify-timeoutm","errorCode":null,"errorMessage":"apify: invalid timeoutMs ${JSON.stringify(timeoutMs)} (must be a positive finite number of milliseconds)","messagePattern":"apify: invalid timeoutMs (.+?) \\(must be a positive finite number of milliseconds\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/apify/_apify.mjs","lineNumber":190,"sourceCode":"async function fetchDatasetItems(runId, token, deadline = null) {\n  const url = `${APIFY_API_BASE}/actor-runs/${runId}/dataset/items`;\n  const items = await fetchJson(\n    url,\n    { headers: authHeaders(token) },\n    PER_REQUEST_TIMEOUT_MS * 2,\n    CONNECT_RETRY_ATTEMPTS,\n    deadline,\n  );\n  if (!Array.isArray(items)) {\n    throw new Error(`Apify run ${runId} returned non-array dataset payload`);\n  }\n  return items;\n}\n\nexport async function runActor(actorId, input, { timeoutMs = DEFAULT_RUN_TIMEOUT_MS, token = process.env.APIFY_TOKEN } = {}) {\n  if (!token) throw new Error('APIFY_TOKEN not set');\n  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n    throw new Error(`apify: invalid timeoutMs ${JSON.stringify(timeoutMs)} (must be a positive finite number of milliseconds)`);\n  }\n  // Single deadline shared across startRun → waitForRun → fetchDatasetItems so\n  // the caller's timeoutMs is the end-to-end ceiling, not just the wait loop.\n  const deadline = Date.now() + timeoutMs;\n  const runId = await startRun(actorId, input, token, deadline);\n  const run = await waitForRun(runId, token, deadline, timeoutMs);\n  if (run.status !== 'SUCCEEDED') {\n    const reason = run.statusMessage ? `: ${run.statusMessage}` : '';\n    throw new Error(`Apify actor ${actorId} finished with status ${run.status}${reason}`);\n  }\n  return await fetchDatasetItems(runId, token, deadline);\n}\n","sourceCodeStart":172,"sourceCodeEnd":203,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/plugins/apify/_apify.mjs#L172-L203","documentation":"Options validation in the Apify plugin's runActor: the timeoutMs option (defaulting to DEFAULT_RUN_TIMEOUT_MS) is not a positive finite number — it is NaN, negative, zero, Infinity, or a non-number. The interpolated JSON.stringify shows the exact bad value; the input at fault is the timeoutMs key of the options object passed by the caller (config plugins.yml or a wrapper).","triggerScenarios":"Calling runActor with timeoutMs = 0, a negative number, NaN, Infinity, a string like '30000', or null/undefined coerced from bad config.","commonSituations":"Reading a timeout from YAML/JSON config where it comes in as a string; defaulting timeout from an env var that is unset (Number(undefined) = NaN); accidentally passing seconds instead of milliseconds (0 or negative after math).","solutions":["Pass a positive finite number of ms, e.g. runActor(actorId, input, { timeoutMs: 30000 }).","If reading from config, coerce with Number(value) and validate Number.isFinite before calling.","Check units: the value is milliseconds; convert seconds with sec * 1000."],"exampleFix":"// before\nawait runActor('user/actor', {}, { timeoutMs: config.timeout }); // '30' (string)\n// after\nconst timeoutMs = Number(config.timeout) * 1000;\nif (!Number.isFinite(timeoutMs) || timeoutMs <= 0) throw new Error('bad timeout');\nawait runActor('user/actor', {}, { timeoutMs });","handlingStrategy":"validation","validationCode":"const ms = Number(rawTimeoutMs);\nif (!Number.isFinite(ms) || ms <= 0) throw new Error(`invalid timeoutMs: ${rawTimeoutMs}`);","typeGuard":"const isValidTimeout = (v) => typeof v === 'number' && Number.isFinite(v) && v > 0;","tryCatchPattern":"try {\n  const items = await runActor(actorId, input, { timeoutMs });\n} catch (e) {\n  if (String(e.message).startsWith('apify: invalid timeoutMs')) {\n    console.error('Fix timeout config; must be positive finite ms');\n  }\n  throw e;\n}","preventionTips":["Coerce config values with Number() before passing numeric options.","Standardize on milliseconds and convert seconds at the config boundary.","Add a startup validation step for numeric config values.","Avoid undefined fallbacks like Number(env.X) without a default."],"tags":["apify","validation","timeout","argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}