{"record":{"id":"90a94961f4d9d17b","repo":"affaan-m/ECC","slug":"sampleintervalms-must-be-positive-and-finite","errorCode":null,"errorMessage":"sampleIntervalMs must be positive and finite","messagePattern":"sampleIntervalMs must be positive and finite","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/control-pane/control-plane-view.js","lineNumber":325,"sourceCode":"    limits: [\n      'Advisories use static thresholds; no learned threshold and no conflict-reduction claim.',\n      'Projection is a display over the shipped channels x_tree, x_overlap, x_dep; it does not change risk.',\n      'Inventory rows are declared-only observations; leases are not locks.',\n      'The view does not steer, pause or lock any agent.'\n    ]\n  };\n}\n\n/**\n * Stateful view builder for a long-lived server: keeps one projection window\n * so z-scores roll over ticks. `buildSnapshot()` is injected (it is the\n * control-pane snapshot with includeProximity: true).\n */\nfunction createControlPlaneViewSource(deps = {}) {\n  const window = deps.window || createProjectionWindow(deps.projection || {});\n  const clock = deps.clock || Date.now;\n  const interval = deps.sampleIntervalMs === undefined ? 5000 : deps.sampleIntervalMs;\n  if (!Number.isFinite(interval) || interval <= 0) throw new Error('sampleIntervalMs must be positive and finite');\n  let cached = null;\n  let pending = null;\n  let expiresAt = 0;\n  async function refresh() {\n    const snapshot = await deps.buildSnapshot();\n    const view = buildControlPlaneView(snapshot, { ...deps.viewOptions, window });\n    cached = { snapshot, view };\n    expiresAt = clock() + interval;\n    return cached;\n  }\n  return {\n    window,\n    async build(extra = {}) {\n      if (!cached || clock() >= expiresAt) {\n        if (!pending) pending = refresh().finally(() => { pending = null; });\n        await pending;\n      }\n      if (Object.keys(extra).length === 0) return cached.view;","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/control-pane/control-plane-view.js#L307-L343","documentation":"createControlPlaneViewSource validates its sampleIntervalMs dependency: if provided it must be a finite number greater than zero. The interval controls how long cached control-plane snapshots live before a refresh; a zero, negative, or non-numeric value would break the caching/expiry logic, so it is rejected at construction time.","triggerScenarios":"Calling createControlPlaneViewSource({ sampleIntervalMs: 0 }) or { sampleIntervalMs: -1 }, or passing a non-finite value (NaN, Infinity) or a string like '5000' instead of a number. Omitting it is fine (defaults to 5000).","commonSituations":"Reading the interval from an env var or query string without Number conversion (getting a string); a config file exporting 0 meaning 'no delay'; arithmetic producing NaN before construction.","solutions":["Pass a positive finite number, e.g. sampleIntervalMs: 5000","Convert config values with Number()/parseInt and validate with Number.isFinite before passing","If you want 'no sampling', omit sampleIntervalMs entirely and use the 5000ms default rather than passing 0","Fix the upstream computation that produced NaN or 0"],"exampleFix":"// before\ncreateControlPlaneViewSource({ sampleIntervalMs: process.env.SAMPLE_MS })\n// after\nconst ms = Number(process.env.SAMPLE_MS);\ncreateControlPlaneViewSource({ sampleIntervalMs: Number.isFinite(ms) && ms > 0 ? ms : undefined });","handlingStrategy":"validation","validationCode":"function validInterval(ms) { return ms === undefined || (Number.isFinite(ms) && ms > 0); }\n// only pass sampleIntervalMs if validInterval(sampleIntervalMs)","typeGuard":"const isPositiveFinite = (n) => typeof n === 'number' && Number.isFinite(n) && n > 0;","tryCatchPattern":"try { createControlPlaneViewSource(deps); } catch (e) {\n  if (String(e.message).includes('sampleIntervalMs')) console.error('Fix sampleIntervalMs:', deps.sampleIntervalMs);\n  else throw e;\n}","preventionTips":["Coerce env/config values with Number() before passing","Never pass 0 to mean 'no delay'; omit the option instead","Unit-test config parsing that feeds sampleIntervalMs","Keep interval values as numbers end-to-end, not strings"],"tags":["validation","config","control-plane"],"backgroundTag":"invalid-argument-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}