CherryHQ/cherry-studio · error · Error

Invalid server type

Error message

Invalid server type

What it means

Thrown during transport creation when a server has a `baseUrl` set but its type (after applying typeOverride ?? server.type ?? 'sse') is neither 'streamableHttp' nor 'sse'. The URL-based transport branch only handles these two protocols; 'stdio' and 'inMemory' types with a baseUrl are contradictory and fall through to this guard.

Source

Thrown at src/main/ai/mcp/McpRuntimeService.ts:538

              getServerLogger(server).debug(`StreamableHTTPClientTransport options`, {
                options: redactSensitive(options)
              })
              return new StreamableHTTPClientTransport(new URL(server.baseUrl), options)
            } else if (urlBasedType === 'sse') {
              const options: SSEClientTransportOptions = {
                eventSourceInit: {
                  fetch: async (url, init) => {
                    return net.fetch(typeof url === 'string' ? url : url.toString(), init)
                  }
                },
                requestInit: {
                  headers: prepareHeaders()
                },
                authProvider
              }
              return new SSEClientTransport(new URL(server.baseUrl), options)
            } else {
              throw new Error('Invalid server type')
            }
          } else if (server.command) {
            let cmd = server.command
            let effectiveCommand = server.command

            // Build a local env for the transport instead of mutating `server.env`. getServerKey(server)
            // serializes server.env, so mutating it here would shift the key after connect — connect-time
            // logs (emitServerLog) and list-changed cache invalidations would then land under a key that
            // getServerLogs / the caches (which see the un-mutated server) never query. Keep server.env
            // untouched so the key stays stable everywhere; see the "deep-copy don't mutate" pattern.
            const connectEnv: Record<string, string> = { ...server.env }

            // Get login shell environment first - needed for command detection and server execution
            // Note: getShellEnv() is memoized, so subsequent calls are fast
            const loginShellEnv = await getShellEnv()

            // For package servers, use resolved configuration with platform overrides and variable substitution
            if (server.dxtPath) {

View on GitHub (pinned to 726446b54c)

Solutions

  1. Set the server type to 'sse' or 'streamableHttp' when using a baseUrl
  2. If the server is command-based (local), remove the baseUrl and set the command field instead
  3. Check the MCP settings UI to ensure the type dropdown matches the connection method (URL vs command)
  4. If importing a server config programmatically, validate that type and baseUrl/command are consistent

Example fix

// before
const server = {
  name: 'my-server',
  baseUrl: 'https://mcp.example.com/sse',
  type: 'stdio'  // contradictory
}

// after
const server = {
  name: 'my-server',
  baseUrl: 'https://mcp.example.com/sse',
  type: 'sse'
}
Defensive patterns

Strategy: validation

Validate before calling

function validateServerTypeConsistency(server: McpServer): void {
  if (server.baseUrl && server.type && !['sse', 'streamableHttp'].includes(server.type)) {
    throw new Error(`Server with baseUrl must use type 'sse' or 'streamableHttp', got '${server.type}'`)
  }
  if (server.command && server.type && !['stdio'].includes(server.type) && !server.baseUrl) {
    // command-based servers typically use stdio
  }
}

Type guard

function isUrlBasedServerType(type: McpServerType | undefined): boolean {
  return type === 'sse' || type === 'streamableHttp'
}

Try / catch

try {
  await runtime.getOrCreateClient(server)
} catch (e) {
  if (e instanceof Error && e.message === 'Invalid server type') {
    // Fix the type field or remove baseUrl, then retry
    server.type = server.baseUrl ? 'sse' : 'stdio'
  }
  throw e
}

Prevention

When it happens

Trigger: A server entity has `baseUrl` populated and `type` set to 'stdio' or 'inMemory'. The transport selection logic checks `server.baseUrl` first, then branches on `urlBasedType`; if urlBasedType isn't 'sse' or 'streamableHttp', it throws.

Common situations: Server was configured with a remote URL but type was accidentally set to 'stdio'; a migration or import set the type incorrectly; the user mixed up local (command-based) and remote (URL-based) server configurations.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/4c43d2d6b5bf8159. Report an issue: GitHub.