github/copilot-sdk · error
Factory limit " " must be a positive integer
Error message
Factory limit "${field}" must be a positive integer What it means
defineFactory validates subagent limits at factory definition time. maxConcurrentSubagents and maxTotalSubagents, when provided, must be positive integers — they cap how many subagents may run concurrently and in total. Zero, negative, or non-integer values are meaningless caps and are rejected up front.
Solutions
- Provide positive whole numbers (>= 1) for both limit fields, or omit them entirely for defaults.
- Coerce and validate external values: Number.parseInt + Number.isInteger before passing them in.
- Use undefined (not 0) to express 'no explicit cap'.
- Validate config values at startup with the same checks the factory performs.
Example fix
// before
defineFactory({ limits: { maxConcurrentSubagents: Number(process.env.MAX_SUBAGENTS) } }); // "0"/"" -> throws
// after
const n = Number.parseInt(process.env.MAX_SUBAGENTS ?? '', 10);
defineFactory({ limits: Number.isInteger(n) && n > 0 ? { maxConcurrentSubagents: n } : {} }); Defensive patterns
Strategy: validation
Validate before calling
function assertPositiveInt(v: unknown, name: string): void {
if (v !== undefined && (!Number.isInteger(v) || (v as number) <= 0)) {
throw new Error(`Factory limit "${name}" must be a positive integer`);
}
}
assertPositiveInt(limits.maxConcurrentSubagents, 'maxConcurrentSubagents');
assertPositiveInt(limits.maxTotalSubagents, 'maxTotalSubagents'); Type guard
const isPositiveInt = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v > 0;
Try / catch
try {
defineFactory({ limits });
} catch (e) {
if (e instanceof Error && e.message.includes('must be a positive integer')) {
limits = {}; // fall back to defaults
} else throw e;
} Prevention
- Parse numeric env/config values with Number.parseInt/Number before passing them in.
- Omit a limit field entirely instead of using 0 for 'unlimited'.
- Validate limits with Number.isInteger + > 0 at config load time.
- Beware fractional arithmetic results when computing limits dynamically.
When it happens
Trigger: Passing limits.maxConcurrentSubagents or limits.maxTotalSubagents as 0, a negative number, a float (e.g. 2.5), NaN, or a numeric string like "5" when calling defineFactory()/validateLimits().
Common situations: Loading limits from config/env where values arrive as strings and are not parsed; computing a limit with arithmetic that yields 0 or a fraction; typos using 0 to mean 'unlimited' (omit the field instead).
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
- Client is in Mode=ModeEmpty but the session config did not…
- CliUrl is mutually exclusive with CliPath
- CopilotClient is in Mode = CopilotClientMode.Empty but the…
- err.Error()
- Factory limit "maxAiCredits" must be a positive, finite…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/1cf497dad30971a6.
Report an issue: GitHub.
Appendix: source
Thrown at nodejs/src/factory.ts:428
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
Object.freeze(value);
for (const nested of Object.values(value)) {
deepFreeze(nested);
}
}
return value;
}
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`
);View on GitHub (pinned to cd8cf15dc3)