github/copilot-sdk · error

Factory limit "timeoutSeconds" must be a positive, finite…

Error message

Factory limit "timeoutSeconds" must be a positive, finite number of seconds

What it means

This error is thrown by validateLimits when a factory definition specifies a timeoutSeconds limit that is not a finite positive number. The library validates factory limits at defineFactory time so invalid configuration fails fast instead of producing undefined behavior at runtime. timeoutSeconds controls how long factory operations may run, so zero, negative, NaN, or Infinity values are meaningless and rejected.

Solutions

  1. Pass a positive finite number of seconds for limits.timeoutSeconds, e.g. 30.
  2. If the value comes from config or env, validate/coerce it before calling defineFactory (Number.isFinite check).
  3. Fix unit conversions so the result is in seconds, not milliseconds or a NaN-producing operation.
  4. Remove the timeoutSeconds field entirely if you do not intend to set a timeout.

Example fix

// before
defineFactory({ name: 'build', limits: { timeoutSeconds: Number(process.env.TIMEOUT) } });
// after
const t = Number(process.env.TIMEOUT);
defineFactory({ name: 'build', limits: { timeoutSeconds: Number.isFinite(t) && t > 0 ? t : 30 } });
Defensive patterns

Strategy: validation

Validate before calling

function isValidTimeout(t) { return typeof t === 'number' && Number.isFinite(t) && t > 0 && t <= 2147483.647; }
if (!isValidTimeout(opts.limits?.timeoutSeconds)) throw new TypeError('timeoutSeconds must be a positive finite number of seconds');

Type guard

function hasValidTimeout(l) { return l.timeoutSeconds === undefined || (Number.isFinite(l.timeoutSeconds) && l.timeoutSeconds > 0); }

Try / catch

try {
  defineFactory({ ...meta, limits: { timeoutSeconds: t } });
} catch (e) {
  if (String(e.message).includes('"timeoutSeconds"')) {
    console.error('Bad timeoutSeconds config:', t);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling defineFactory with limits.timeoutSeconds set to 0, a negative number, NaN, or Infinity. Also occurs when timeoutSeconds is computed dynamically (e.g. from config or env) and the computation yields NaN or a non-positive value.

Common situations: Reading timeout values from environment variables or JSON config where the value is a string or missing and becomes NaN after numeric coercion; a config template with a placeholder 0; mixing units (milliseconds vs seconds) and dividing wrongly.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/63952f778c6541bc. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/factory.ts:436

function validateLimits(meta: FactoryMeta): void {
    const limits = meta.limits;
    if (!limits) {
        return;
    }

    for (const field of ["maxConcurrentSubagents", "maxTotalSubagents"] as const) {
        const value = limits[field];
        if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {
            throw new Error(`Factory limit "${field}" must be a positive integer`);
        }
    }

    if (
        limits.timeoutSeconds !== undefined &&
        (!Number.isFinite(limits.timeoutSeconds) || limits.timeoutSeconds <= 0)
    ) {
        throw new Error(
            'Factory limit "timeoutSeconds" must be a positive, finite number of seconds'
        );
    }
    if (
        limits.timeoutSeconds !== undefined &&
        limits.timeoutSeconds > MAX_FACTORY_TIMEOUT_SECONDS
    ) {
        throw new Error(
            `Factory limit "timeoutSeconds" must not exceed ${MAX_FACTORY_TIMEOUT_SECONDS} seconds`
        );
    }

    if (limits.maxAiCredits !== undefined) {
        const maxNanoAiu = Math.round(limits.maxAiCredits * NANO_AIU_PER_AIU);
        if (
            !Number.isFinite(limits.maxAiCredits) ||
            limits.maxAiCredits <= 0 ||
            !Number.isSafeInteger(maxNanoAiu) ||

View on GitHub (pinned to cd8cf15dc3)