payloadcms/payload · error · InvalidConfiguration

`jobs.processingLease.safetyBuffer` must be non-negative and

Error message

`jobs.processingLease.safetyBuffer` must be non-negative and less than `jobs.processingLease.duration`.

What it means

Thrown at sanitize time when `jobs.processingLease.safetyBuffer` is negative or not strictly less than `jobs.processingLease.duration`. The lease model lets a worker claim a job for `duration` ms and reserves `safetyBuffer` ms of slack before another worker can reclaim a stalled job; an invalid relationship between the two would cause double-execution or premature requeueing.

Source

Thrown at packages/payload/src/config/sanitize.ts:255

    minWidth: 'x-small',
  })
  dashboard.defaultLayout ??= [
    {
      widgetSlug: 'collections',
      width: 'full',
    } satisfies WidgetInstance,
    {
      widgetSlug: 'activity',
      width: 'small',
    } satisfies WidgetInstance,
  ]
}

export const sanitizeConfig = (incomingConfig: Config): SanitizedConfig => {
  const configWithDefaults = addDefaultsToConfig(incomingConfig)
  const { duration, safetyBuffer } = configWithDefaults.jobs!.processingLease!
  if (!(safetyBuffer! >= 0 && safetyBuffer! < duration!)) {
    throw new InvalidConfiguration(
      '`jobs.processingLease.safetyBuffer` must be non-negative and less than `jobs.processingLease.duration`.',
    )
  }

  const config: Partial<SanitizedConfig> = sanitizeAdminConfig(configWithDefaults)

  if (!config.endpoints) {
    config.endpoints = []
  }

  if (configWithDefaults.collections?.some(({ upload }) => upload)) {
    config.endpoints.push(uploadInstructionsEndpoint, ...stagedUploadEndpoints)
  }

  for (const endpoint of authRootEndpoints) {
    config.endpoints.push(endpoint)
  }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure `0 <= safetyBuffer < duration` (both in milliseconds), e.g. `duration: 90_000, safetyBuffer: 15_000`.
  2. If unsure, remove both options and let Payload apply its defaults.
  3. Re-check after any change to job/queue config in plugins.

Example fix

// before
jobs: { processingLease: { duration: 10_000, safetyBuffer: 30_000 } }
// after
jobs: { processingLease: { duration: 90_000, safetyBuffer: 15_000 } }
Defensive patterns

Strategy: validation

Validate before calling

const { duration = 90_000, safetyBuffer = 15_000 } = config.jobs?.processingLease ?? {}
if (!(safetyBuffer >= 0 && safetyBuffer < duration)) {
  throw new Error('jobs.processingLease.safetyBuffer must be >= 0 and < duration')
}

Type guard

function isValidLease(l: { duration?: number; safetyBuffer?: number }): boolean {
  const d = l.duration ?? 90_000, s = l.safetyBuffer ?? 15_000
  return s >= 0 && s < d
}

Prevention

When it happens

Trigger: Explicitly setting `jobs.processingLease.safetyBuffer` greater than `duration`; setting a negative safetyBuffer; copying values from another config without recalculating.

Common situations: Tuning job queue reliability settings; long-running tasks prompting an increase of `duration` while leaving `safetyBuffer` larger; misreading the units (both are milliseconds).

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/8313fe28dbcc6c16. Report an issue: GitHub.