ruvnet/ruflo · error · Error

Unknown transport type: ${type}

Error message

Unknown transport type: ${type}

What it means

createTransport() switches on the TransportType union ('stdio' | 'http' | 'websocket' | 'in-process'); any other value falls into the default branch and throws 'Unknown transport type: <type>'. TypeScript rejects invalid literals at compile time, so seeing this at runtime means an unchecked string reached the factory — via a cast, a JS caller, or config/env input.

Source

Thrown at v3/@claude-flow/mcp/src/transport/index.ts:64

        port: config.port as number,
        ...config,
      } as HttpTransportConfig);

    case 'websocket':
      if (!config || !('host' in config) || !('port' in config)) {
        throw new Error('WebSocket transport requires host and port configuration');
      }
      return createWebSocketTransport(logger, {
        host: config.host as string,
        port: config.port as number,
        ...config,
      } as WebSocketTransportConfig);

    case 'in-process':
      return createInProcessTransport(logger);

    default:
      throw new Error(`Unknown transport type: ${type}`);
  }
}

class InProcessTransport implements ITransport {
  public readonly type: TransportType = 'in-process';

  constructor(private readonly logger: ILogger) {}

  async start(): Promise<void> {
    this.logger.debug('In-process transport started');
  }

  async stop(): Promise<void> {
    this.logger.debug('In-process transport stopped');
  }

  onRequest(): void {
    // No-op - requests are handled directly

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Use one of the exact literals: 'stdio', 'http', 'websocket', 'in-process'
  2. Map external names/aliases to the union at the boundary (e.g. ws -> 'websocket')
  3. Validate the value against an allowlist before calling createTransport and fail fast
  4. Keep a typed constant instead of a raw string flowing from config

Example fix

// before
const t = createTransport(process.env.TRANSPORT as TransportType, logger, cfg);

// after
const ALIASES: Record<string, TransportType> = {
  stdio: 'stdio', http: 'http', ws: 'websocket', websocket: 'websocket', 'in-process': 'in-process',
};
const type = ALIASES[(process.env.TRANSPORT ?? '').toLowerCase()];
if (!type) throw new Error(`Invalid TRANSPORT=${process.env.TRANSPORT}. Use stdio|http|websocket|in-process`);
const t = createTransport(type, logger, cfg);
Defensive patterns

Strategy: type-guard

Validate before calling

const TRANSPORT_TYPES = ['stdio', 'http', 'websocket', 'in-process'] as const;
const raw = (process.env.TRANSPORT ?? 'stdio').toLowerCase();
if (!(TRANSPORT_TYPES as readonly string[]).includes(raw)) {
  throw new Error(`Invalid transport '${raw}'. Use: ${TRANSPORT_TYPES.join('|')}`);
}
const t = createTransport(raw as TransportType, logger, cfg);

Type guard

const TRANSPORT_TYPES = ['stdio', 'http', 'websocket', 'in-process'] as const;
function isTransportType(v: unknown): v is (typeof TRANSPORT_TYPES)[number] {
  return typeof v === 'string' && (TRANSPORT_TYPES as readonly string[]).includes(v);
}

Prevention

When it happens

Trigger: Reading the transport name from an env var, CLI flag, or config file (e.g. TRANSPORT=ws instead of 'websocket'); casting with `as TransportType`; legacy aliases like 'sse' or 'Websocket' from an older version or different casing.

Common situations: Deploying with a config written for an older CLI vocabulary; case/casing mismatches in docker-compose or Kubernetes env vars; string interpolation assembling the type name.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/8b56b302fd0600ba. Report an issue: GitHub.