paperclipai/paperclip · error

PAPERCLIP_VITE_HMR_PROTOCOL must be ws or wss

Error message

PAPERCLIP_VITE_HMR_PROTOCOL must be ws or wss

What it means

Environment-variable validation in resolveViteHmrProtocol: PAPERCLIP_VITE_HMR_PROTOCOL is set but is neither 'ws' nor 'wss' (case-sensitive after trim/lowercase handling upstream). The value is passed straight into Vite's HMR config which only accepts those two protocols, so dev-server startup aborts with this guard.

Solutions

  1. Set PAPERCLIP_VITE_HMR_PROTOCOL to ws or wss.
  2. Unset PAPERCLIP_VITE_HMR_PROTOCOL to use the default.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/app.ts:162 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/f2653a58a59f29e6. Report an issue: GitHub.

Appendix: source

Thrown at server/src/app.ts:231

export function resolveViteHmrHost(bindHost: string): string | undefined {
  const normalized = bindHost.trim().toLowerCase();
  if (
    normalized === "0.0.0.0" ||
    normalized === "::" ||
    normalized === "127.0.0.1" ||
    normalized === "::1" ||
    normalized === "localhost"
  )
    return undefined;
  return bindHost;
}

export function resolveViteHmrProtocol(
  value: string | undefined,
): "ws" | "wss" | undefined {
  if (!value) return undefined;
  if (value === "ws" || value === "wss") return value;
  throw new Error("PAPERCLIP_VITE_HMR_PROTOCOL must be ws or wss");
}

export function listenViteHmrServer(
  server: HttpServer,
  port: number,
  bindHost: string,
): Promise<void> {
  return new Promise((resolve, reject) => {
    const onError = (error: Error) => {
      server.off("listening", onListening);
      reject(error);
    };
    const onListening = () => {
      server.off("error", onError);
      resolve();
    };
    server.once("error", onError);
    server.once("listening", onListening);

View on GitHub (pinned to 3f1d897a7c)