github/copilot-sdk · error

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

Error message

Factory limit "maxAiCredits" must be a positive, finite number that rounds to a safe positive integer nano-AIU ceiling

What it means

This error is thrown by validateLimits when maxAiCredits is not a positive finite number, or when the value multiplied by NANO_AIU_PER_AIU and rounded does not yield a safe positive integer nano-AIU ceiling. The runtime tracks AI credit budgets in nano-AIU (integer units), so the configured credit value must map cleanly onto that integer representation.

Solutions

  1. Pass a positive finite maxAiCredits large enough to round to at least 1 nano-AIU, e.g. 1.
  2. Replace Infinity/0 sentinel values with a concrete positive budget.
  3. Validate the value with Number.isFinite before calling defineFactory.
  4. Choose a smaller value if the converted nano-AIU total exceeds Number.MAX_SAFE_INTEGER.

Example fix

// before
defineFactory({ name: 'agent', limits: { maxAiCredits: Infinity } });
// after
defineFactory({ name: 'agent', limits: { maxAiCredits: 100 } });
Defensive patterns

Strategy: validation

Validate before calling

function isValidCredits(c) {
  const maxNanoAiu = Math.round(c * NANO_AIU_PER_AIU);
  return Number.isFinite(c) && c > 0 && Number.isSafeInteger(maxNanoAiu) && maxNanoAiu >= 1;
}
if (!isValidCredits(opts.limits?.maxAiCredits)) throw new TypeError('maxAiCredits must map to a safe positive integer nano-AIU ceiling');

Type guard

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

Try / catch

try {
  defineFactory({ ...meta, limits: { maxAiCredits: credits } });
} catch (e) {
  if (String(e.message).includes('maxAiCredits')) console.error('Bad maxAiCredits:', credits);
  throw e;
}

Prevention

When it happens

Trigger: Calling defineFactory with limits.maxAiCredits set to 0, a negative number, NaN, or Infinity; or with a fractional value so small that Math.round(maxAiCredits * NANO_AIU_PER_AIU) rounds to 0 (below the representable minimum); or so large that it exceeds Number.MAX_SAFE_INTEGER in nano-AIU.

Common situations: Passing a decimal like 0.0000001 that rounds to zero nano-AIU; NaN from a failed config parse; Infinity from an attempted 'unlimited' setting; extremely large budgets overflowing the safe integer range.

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/68bd745d95834469. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/factory.ts:457

    }
    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) ||
            maxNanoAiu < 1
        ) {
            throw new Error(
                'Factory limit "maxAiCredits" must be a positive, finite number that rounds to a safe positive integer nano-AIU ceiling'
            );
        }
    }
}

function validatePhases(meta: FactoryMeta): void {
    const titles = new Set<string>();
    for (const phase of meta.phases) {
        if (phase.title.trim().length === 0) {
            throw new Error("Factory phase titles must not be empty");
        }
        if (titles.has(phase.title)) {
            throw new Error(`Factory phase title "${phase.title}" is declared more than once`);
        }
        titles.add(phase.title);
    }
}

View on GitHub (pinned to cd8cf15dc3)