{"record":{"id":"3c995a65ef60e57b","repo":"mastra-ai/mastra","slug":"platform-github-issue-reconcile-interval-must-be-a","errorCode":null,"errorMessage":"Platform GitHub issue reconcile interval must be a positive number.","messagePattern":"Platform GitHub issue reconcile interval must be a positive number\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/integrations/platform/github/event-worker.ts","lineNumber":156,"sourceCode":"    this.#controller = config.controller;\n    this.#github = config.github;\n    this.#storage = config.storage;\n    this.#ingestFactoryEvent = config.ingestFactoryEvent;\n    this.#reconcileFactoryState = config.reconcileFactoryState;\n    this.#reconcileIssuesFactoryState = config.reconcileIssuesFactoryState;\n    this.#pollEventsEnabled = config.pollEventsEnabled ?? true;\n    const legacyReconcileIntervalMs = config.reconcileIntervalMs ?? DEFAULT_RECONCILE_INTERVAL_MS;\n    this.#pullRequestReconcileIntervalMs = config.pullRequestReconcileIntervalMs ?? legacyReconcileIntervalMs;\n    this.#issueReconcileIntervalMs = config.issueReconcileIntervalMs ?? legacyReconcileIntervalMs;\n    this.#intervalMs = config.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n    if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) {\n      throw new Error('Platform GitHub event polling interval must be a positive number.');\n    }\n    if (!Number.isFinite(this.#pullRequestReconcileIntervalMs) || this.#pullRequestReconcileIntervalMs <= 0) {\n      throw new Error('Platform GitHub pull request reconcile interval must be a positive number.');\n    }\n    if (!Number.isFinite(this.#issueReconcileIntervalMs) || this.#issueReconcileIntervalMs <= 0) {\n      throw new Error('Platform GitHub issue reconcile interval must be a positive number.');\n    }\n    this.#leaseTtlMs = Math.max(\n      MIN_LEASE_TTL_MS,\n      Math.min(this.#intervalMs, this.#pullRequestReconcileIntervalMs, this.#issueReconcileIntervalMs) * 3,\n    );\n    this.#now = config.now ?? Date.now;\n    this.#dispatch = config.dispatch ?? dispatchGithubWebhook;\n    this.#sourceControl = config.sourceControl;\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('PlatformGithubEventWorker: call init() before start()');","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/integrations/platform/github/event-worker.ts#L138-L174","documentation":"Thrown from the PlatformGithubEventWorker constructor (event-worker.ts:156) when config.issueReconcileIntervalMs (or the legacy reconcileIntervalMs fallback) is provided but is not a finite number greater than 0. This interval controls how often issues are reconciled with GitHub; the constructor fails fast because a non-positive value would produce a busy loop.","triggerScenarios":"new PlatformGithubEventWorker({ ..., issueReconcileIntervalMs: 0 }) or a negative/NaN/Infinity value; the same bad value reaching it via legacy config.reconcileIntervalMs when issueReconcileIntervalMs is unset.","commonSituations":"Issue-specific reconcile timing added recently and seeded from an unset env var (Number('') === 0 or NaN); copy-paste config where only the PR interval was filled in; unvalidated dashboard/admin-supplied tuning values.","solutions":["Set issueReconcileIntervalMs to a positive finite number of milliseconds.","Omit the field so it inherits the sane default via reconcileIntervalMs/DEFAULT_RECONCILE_INTERVAL_MS.","Sanitize env- or config-derived numbers: only pass them when Number.isFinite(v) && v > 0.","Set a correct legacy reconcileIntervalMs if both PR and issue intervals should share one value."],"exampleFix":"// before\nnew PlatformGithubEventWorker({ issueReconcileIntervalMs: Number(config.issues?.reconcileMs ?? 0) });\n\n// after\nconst v = Number(config.issues?.reconcileMs);\nnew PlatformGithubEventWorker({\n  ...(Number.isFinite(v) && v > 0 ? { issueReconcileIntervalMs: v } : {}),\n});","handlingStrategy":"validation","validationCode":"const raw = config.issueReconcileIntervalMs ?? config.reconcileIntervalMs;\nif (raw !== undefined && !(Number.isFinite(Number(raw)) && Number(raw) > 0)) {\n  throw new TypeError(`issueReconcileIntervalMs must be positive, got ${String(raw)}`);\n}","typeGuard":"function isValidInterval(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v > 0;\n}","tryCatchPattern":"try {\n  const worker = new PlatformGithubEventWorker(config);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('issue reconcile interval')) {\n    logger.error('Invalid issueReconcileIntervalMs', { value: config.issueReconcileIntervalMs });\n  }\n  throw err;\n}","preventionTips":["Validate env-derived numbers with Number.isFinite and > 0 before use.","Keep PR and issue reconcile intervals sourced from one validated value unless tuned separately.","Reject 0/negative values at the config-loading layer with a clear message.","Cover worker construction with a unit test that feeds production config."],"tags":["configuration","validation","github","worker"],"backgroundTag":"invalid-configuration-value","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}