paperclipai/paperclip · error · ProtocolError
invalid_port
invalid_port
Error message
an app listener in the dedicated app range is required
What it means
Semantic listener check in decodeRequest for expose requests: the runtime declared only non-app listeners, but at least one listener with an app purpose inside the dedicated app port range is required. ProtocolError('invalid_port') surfaces the policy violation after each port passed assertCanonicalPort.
Source
Thrown at packages/tailscale-https-broker/src/protocol.ts:162
try {
port = assertCanonicalPort(listener.port);
} catch (error) {
throw new ProtocolError("invalid_port", (error as Error).message, requestId);
}
return { purpose: purpose as OwnedListener["purpose"], port };
});
// Reject duplicate ports / duplicate purposes within one request.
const ports = new Set(listeners.map((l) => l.port));
const purposes = new Set(listeners.map((l) => l.purpose));
if (ports.size !== listeners.length || purposes.size !== listeners.length) {
throw new ProtocolError("malformed_request", "duplicate listener port or purpose", requestId);
}
const app = listeners.find((listener) => listener.purpose === "app");
const hmr = listeners.find((listener) => listener.purpose === "vite_hmr");
if (!app || app.port < DEFAULT_APP_PORT_MIN || app.port > DEFAULT_APP_PORT_MAX) {
throw new ProtocolError("invalid_port", "an app listener in the dedicated app range is required", requestId);
}
if (hmr && hmr.port !== app.port + DEFAULT_HMR_PORT_OFFSET) {
throw new ProtocolError("invalid_port", "vite_hmr must be the app port companion", requestId);
}
return { op: "reserve", requestId, runtimeId, listeners };
}
function assertExactKeys(
obj: Record<string, unknown>,
allowed: string[],
requestId: string | null,
): void {
const allowedSet = new Set(allowed);
for (const key of Object.keys(obj)) {
if (!allowedSet.has(key)) {
throw new ProtocolError("malformed_request", `unknown field: ${key}`, requestId);
}View on GitHub (pinned to 120ae5428f)
Solutions
- Configure at least one app listener within the dedicated app port range before issuing this request.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/tailscale-https-broker/src/protocol.ts:162 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/8dcc062d688498ca.
Report an issue: GitHub.