{"record":{"id":"422dd0ee62aa541b","repo":"mastra-ai/mastra","slug":"github-pull-request-reconcile-interval-must-be-a-p","errorCode":null,"errorMessage":"GitHub pull request reconcile interval must be a positive number.","messagePattern":"GitHub pull request reconcile interval must be a positive number\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/integrations/github/reconcile-worker.ts","lineNumber":78,"sourceCode":"  #running = false;\n  #timer: ReturnType<typeof setTimeout> | undefined;\n  #inFlight: Promise<void> | undefined;\n  #leaseProvider: LeaseProvider = NoopLeaseProvider;\n  #nextPullRequestReconcileAt = 0;\n  #nextIssueReconcileAt = 0;\n\n  constructor(config: GithubReconcileWorkerConfig) {\n    super();\n    if (!config.reconcile && !config.reconcileIssues) {\n      throw new Error('GitHub reconcile worker requires a pull request or issue reconciler.');\n    }\n    this.#reconcile = config.reconcile;\n    this.#reconcileIssues = config.reconcileIssues;\n    this.#sourceControl = config.sourceControl;\n    this.#intervalMs = config.intervalMs ?? DEFAULT_GITHUB_RECONCILE_INTERVAL_MS;\n    this.#issueIntervalMs = config.issueIntervalMs ?? this.#intervalMs;\n    if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) {\n      throw new Error('GitHub pull request reconcile interval must be a positive number.');\n    }\n    if (!Number.isFinite(this.#issueIntervalMs) || this.#issueIntervalMs <= 0) {\n      throw new Error('GitHub issue reconcile interval must be a positive number.');\n    }\n    this.#leaseTtlMs = Math.max(MIN_LEASE_TTL_MS, Math.min(this.#intervalMs, this.#issueIntervalMs) * 3);\n    this.#now = config.now ?? Date.now;\n  }\n\n  async init(deps: WorkerDeps): Promise<void> {\n    await super.init(deps);\n    this.#leaseProvider = getLeaseProvider(deps.pubsub);\n  }\n\n  async start(): Promise<void> {\n    if (this.#running) return;\n    if (!this.deps) throw new Error('GithubReconcileWorker: call init() before start()');\n    this.#running = true;\n    this.deps.logger.info('GitHub reconcile worker started', {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/integrations/github/reconcile-worker.ts#L60-L96","documentation":"The constructor validates that intervalMs is a finite number greater than zero before scheduling pull request reconciliation. NaN, 0, negative, or Infinity intervals would break timers and lease math, so construction fails immediately.","triggerScenarios":"new GithubReconcileWorker({ reconcile, intervalMs: 0 }) — or intervalMs parsed from an env var string ('NaN'), a negative value, or Number(undefined) leaking NaN through a ?? that never triggers because a non-null invalid value was provided.","commonSituations":"intervalMs: Number(process.env.INTERVAL) where the env var is unset or non-numeric (NaN passes ?? defaults); specifying milliseconds as seconds; Infinity from a division bug.","solutions":["Pass a finite positive interval in milliseconds, e.g. intervalMs: 60_000.","Sanitize env-derived values: const ms = Number(raw); if (!Number.isFinite(ms) || ms <= 0) use default.","Check for NaN produced by Number(undefined) and fix the defaulting logic.","Omit intervalMs entirely to use DEFAULT_GITHUB_RECONCILE_INTERVAL_MS."],"exampleFix":"// before\nintervalMs: Number(process.env.RECONCILE_INTERVAL), // NaN when unset\n// after\nconst parsed = Number(process.env.RECONCILE_INTERVAL);\nintervalMs: Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;","handlingStrategy":"validation","validationCode":"const intervalMs = config.intervalMs;\nif (intervalMs !== undefined && (!Number.isFinite(intervalMs) || intervalMs <= 0)) throw new Error(`invalid intervalMs: ${intervalMs}`);","typeGuard":"function isPositiveMs(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v > 0;\n}","tryCatchPattern":"try {\n  worker = new GithubReconcileWorker(config);\n} catch (e) {\n  if ((e as Error).message.includes('must be a positive number')) {\n    log.error('bad reconcile interval, falling back to default');\n    worker = new GithubReconcileWorker({ ...config, intervalMs: undefined });\n  } else throw e;\n}","preventionTips":["Sanitize env-derived intervals with Number.isFinite and > 0 checks.","Use a named constant (e.g. 60_000) instead of inline math that can yield NaN.","Remember intervalMs is milliseconds, not seconds.","Omit intervalMs to use the library default."],"tags":["github","configuration","validation"],"backgroundTag":"invalid-interval-config","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}