{"record":{"id":"f7a42a20b417c631","repo":"herdrdev/herdr","slug":"expected-welcome-message","errorCode":null,"errorMessage":"expected Welcome message","messagePattern":"expected Welcome message","errorType":"error_code","errorClass":"ClientError::Protocol","httpStatus":null,"severity":"error","filePath":"src/client/mod.rs","lineNumber":893,"sourceCode":"        stream,\n        None,\n        \"failed to clear client handshake read timeout\",\n    )?;\n\n    match welcome {\n        ServerMessage::Welcome {\n            version,\n            encoding,\n            error,\n        } => {\n            if let Some(error) = error {\n                return Err(ClientError::HandshakeRejected { version, error });\n            }\n            info!(version, ?encoding, \"handshake succeeded\");\n            Ok(encoding)\n        }\n        _ => Err(ClientError::Protocol(protocol::FramingError::Io(\n            io::Error::new(io::ErrorKind::InvalidData, \"expected Welcome message\"),\n        ))),\n    }\n}\n\n// ---------------------------------------------------------------------------\n// Client event loop\n// ---------------------------------------------------------------------------\n\n/// Internal events for the client event loop.\nenum ClientLoopEvent {\n    /// Raw input bytes from stdin.\n    #[cfg(unix)]\n    StdinInput(Vec<u8>),\n    /// One confirmed SGR pixel report with geometry captured by the reader.\n    #[cfg(unix)]\n    PixelMouse(Vec<u8>, crate::input::mouse::HostGeometry),\n    #[cfg(unix)]\n    DirectGraphicsResponse(direct_graphics::Response),","sourceCodeStart":875,"sourceCodeEnd":911,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/client/mod.rs#L875-L911","documentation":"During the client handshake, the first server message must be protocol::ServerMessage::Welcome; any other decoded message yields ClientError::Protocol with io::ErrorKind::InvalidData 'expected Welcome message' (src/client/mod.rs:893). It indicates the stream is alive but is speaking a different protocol or is out of sync — a version/wire mismatch rather than a dead connection.","triggerScenarios":"do_handshake (used by connect_terminal_session_stream and run_client_with_mode) receives a non-Welcome first frame. Happens when a client of one protocol version connects to a server of an incompatible version, or when the socket actually serves a different protocol (wrong socket path).","commonSituations":"Mixing a stable herdr binary with a preview/dev server (or vice versa) sharing one socket, protocol changes without PROTOCOL_VERSION bump, or pointing HERDR_SOCKET_PATH at a non-herdr Unix socket.","solutions":["Make client and server come from the same herdr build/version (herdr update on both, or restart the server with the same binary)","Verify HERDR_SOCKET_PATH/HERDR_CLIENT_SOCKET_PATH point at the herdr-dev or matching server socket, not another service","When developing inside Herdr, use: env -u HERDR_SOCKET_PATH -u HERDR_CLIENT_SOCKET_PATH cargo run -- <cmd>","If you maintain a fork and changed the wire format, bump PROTOCOL_VERSION in src/protocol/wire.rs"],"exampleFix":"# before (debug client talking to stable server socket)\ncargo run -- status\n\n# after\nenv -u HERDR_SOCKET_PATH -u HERDR_CLIENT_SOCKET_PATH cargo run -- status","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match do_handshake(...) {\n    Err(ClientError::Protocol(protocol::FramingError::Io(e)))\n        if e.kind() == io::ErrorKind::InvalidData =>\n        Err(\"client/server protocol mismatch: use matching herdr versions\".into()),\n    r => r,\n}","preventionTips":["Run client and server from the same herdr install","Bump PROTOCOL_VERSION whenever the wire format changes","When testing debug builds, unset inherited socket overrides"],"tags":["protocol","handshake","version-mismatch","rust"],"backgroundTag":"protocol-version-mismatch","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}