paperclipai/paperclip · error
providerLifetimeFenceCandidates must be three distinct priva
Error message
providerLifetimeFenceCandidates must be three distinct private ports
What it means
providerLifetimeFenceCandidates must be exactly three distinct TCP ports in the private/dynamic range (49152-65535); the validator freezes the tuple only when the shape, range, and uniqueness checks all pass. This prevents fence ports from colliding or overlapping with privileged ranges.
Source
Thrown at packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts:1111
: { permissionMode: requiredPermissionMode(input.permissionMode) }),
providerLifetimeFenceCandidates: requiredFenceCandidates(
input.providerLifetimeFenceCandidates,
),
};
}
function requiredFenceCandidates(
value: unknown,
): readonly [number, number, number] {
if (
!Array.isArray(value) ||
value.length !== 3 ||
value.some(
(port) => !Number.isSafeInteger(port) || port < 49_152 || port > 65_535,
) ||
new Set(value).size !== 3
) {
throw new Error(
"providerLifetimeFenceCandidates must be three distinct private ports",
);
}
return Object.freeze([...value]) as readonly [number, number, number];
}
function requiredPermissionMode(
value: unknown,
): AcpxSidecarOpenParams["permissionMode"] {
if (
value === "approve-all" ||
value === "approve-reads" ||
value === "deny-all"
) {
return value;
}
throw new Error(
"permissionMode must be approve-all, approve-reads, or deny-all",View on GitHub (pinned to 01ad858492)
Solutions
- Provide exactly three different ports, each between 49152 and 65535
- Fix the config source so duplicates are resolved before validation
- Generate three distinct ephemeral ports programmatically
Example fix
// before normalizeFenceCandidates([49200, 49200, 49300]); // after normalizeFenceCandidates([49200, 49201, 49300]);
Defensive patterns
Strategy: validation
Validate before calling
function validFencePorts(ports) { return Array.isArray(ports) && ports.length === 3 && ports.every(p => Number.isSafeInteger(p) && p >= 49152 && p <= 65535) && new Set(ports).size === 3; }
if (!validFencePorts(config.providerLifetimeFenceCandidates)) throw new Error('need three distinct ports in 49152-65535'); Type guard
function isFenceCandidateTuple(v: unknown): v is readonly [number, number, number] {
return Array.isArray(v) && v.length === 3 && v.every((p): p is number => Number.isSafeInteger(p) && p >= 49152 && p <= 65535) && new Set(v).size === 3;
} Try / catch
try { configureFences(cfg.providerLifetimeFenceCandidates); }
catch (e) { if (String(e.message).includes('three distinct private ports')) { cfg.providerLifetimeFenceCandidates = pickDistinctEphemeralPorts(3); configureFences(cfg.providerLifetimeFenceCandidates); } else throw e; } Prevention
- Validate port config at load time, before the sidecar starts
- Use a config schema with min/max/uniqueness constraints for port arrays
- Generate ephemeral ports programmatically instead of hardcoding
When it happens
Trigger: Passing an array whose length is not 3, containing non-integer or out-of-range ports (<49152 or >65535), or containing duplicate port values.
Common situations: Config with two or three identical ports from copy-paste; ports picked from the well-known/registered range; a config loader returning a 2-element list after dropping a duplicate.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- ${label} is not a regular file at ${canonical}.
- Claude Managed evals require exact model claude-sonnet-5
- AWS AgentCore evals require exact model global.anthropic.cla
- request.session.provider must match request.provider
- request.session.requestedModel must match request.model
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/1ed6fce29444d339.
Report an issue: GitHub.