jlcodes99/cockpit-tools · warning
[WakeupGateway] 官方 LS SubscribeToUnifiedStateSyncTopic 解析失败:
Error message
[WakeupGateway] 官方 LS SubscribeToUnifiedStateSyncTopic 解析失败: {} What it means
For POSTs matching the SubscribeToUnifiedStateSyncTopic RPC, the local official-LS extension server parses the topic name out of the Connect request body via parse_subscribe_topic_from_connect_body. On failure it logs '官方 LS SubscribeToUnifiedStateSyncTopic 解析失败: {}' and returns HTTP 400 Bad Request, closing the stream. The parser must extract the topic string (e.g. uss-oauth) from the protobuf-encoded body, so the error means the body did not contain a decodable topic field.
Source
Thrown at src-tauri/src/modules/wakeup_gateway.rs:1270
crate::modules::logger::log_error(&format!(
"[WakeupGateway] 官方 LS LanguageServerStarted 解析失败: {}",
err
));
return OfficialLsExtensionAction::Close(text_response(
400,
"Bad Request",
&err,
"text/plain; charset=utf-8",
));
}
}
}
if path_matches_rpc_method(&path, "SubscribeToUnifiedStateSyncTopic") {
let topic = match parse_subscribe_topic_from_connect_body(&parsed.body) {
Ok(v) => v,
Err(err) => {
crate::modules::logger::log_error(&format!(
"[WakeupGateway] 官方 LS SubscribeToUnifiedStateSyncTopic 解析失败: {}",
err
));
return OfficialLsExtensionAction::Close(text_response(
400,
"Bad Request",
&err,
"text/plain; charset=utf-8",
));
}
};
let topic_bytes = match topic.as_str() {
"uss-oauth" => &state.uss_oauth_topic_bytes,
"uss-enterprisePreferences" | "uss-agentPreferences" => &state.empty_topic_bytes,
_ => &state.empty_topic_bytes,
};
let update = build_unified_state_sync_update_initial_state(topic_bytes);View on GitHub (pinned to 1ed8b77992)
Solutions
- Log the raw body length and first bytes with the parse error to see whether an envelope was stripped or the body is empty.
- Update parse_subscribe_topic_from_connect_body to the field number/type used by the installed LS version's SubscribeRequest proto.
- Handle both unary (application/proto) and streaming (application/connect+proto) framing: decode the envelope before extracting the topic string field.
- Return 400 with the parser's message (already done) and skip serving that stream, so one bad subscription does not affect other RPCs on the server.
- If the sender is a legit LS build, diff its bundled .proto against the parser and fix the field mapping, then add a unit test with a captured request body.
Example fix
// before: single-shot parse, opaque failure
let topic = match parse_subscribe_topic_from_connect_body(&parsed.body) {
Ok(v) => v,
Err(err) => { log_error(&format!("... 解析失败: {}", err)); return Close(text_response(400, "Bad Request", &err, ...)); }
};
// after: strip connect envelope first and include body context in the log
let inner = strip_connect_envelope(&parsed.body, &content_type).unwrap_or(&parsed.body);
match parse_subscribe_topic_from_connect_body(inner) {
Ok(v) => v,
Err(err) => {
log_error(&format!("SubscribeToUnifiedStateSyncTopic 解析失败: {} (len={})", err, inner.len()));
return Close(text_response(400, "Bad Request", &err, "text/plain; charset=utf-8"));
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate framing and presence before topic extraction
fn subscribable(body: &[u8], content_type: &str) -> bool {
let ct = content_type.to_ascii_lowercase();
(ct.starts_with("application/connect+proto") || ct.starts_with("application/proto")) && !body.is_empty()
} Try / catch
// Handle per-request parse failure without killing the extension server
let topic = match parse_subscribe_topic_from_connect_body(&parsed.body) {
Ok(v) => v,
Err(err) => {
log_error(&format!("SubscribeToUnifiedStateSyncTopic 解析失败: {}", err));
return OfficialLsExtensionAction::Close(text_response(400, "Bad Request", &err, "text/plain; charset=utf-8"));
}
}; Prevention
- Strip the Connect envelope (length-prefixed frames) before parsing fields for application/connect+proto requests.
- Verify the topic string field number against the installed LS's SubscribeRequest proto after every LS upgrade.
- Keep serving other RPCs after a bad subscription (isolation), and cap failed-parse logging to avoid log floods.
- Record captured request bodies for failing subscriptions to build regression fixtures.
When it happens
Trigger: A client (official LS) subscribes to the unified state sync topic and parse_subscribe_topic_from_connect_body returns Err: the Connect body is empty, the protobuf field holding the topic string is missing or at an unexpected field number/wire type, the envelope framing was stripped incorrectly, or a proto schema change altered the subscription message layout.
Common situations: Official LS upgrade changes the SubscribeToUnifiedStateSyncTopic request proto so the topic field number shifts; client sends a streaming-framed body where the parser expects a single unary message (or vice versa); truncated body from a connection reset mid-request; another process probing the port with non-proto bytes.
Related errors
- [WakeupGateway] 官方 LS LanguageServerStarted 解析失败: {}
- invalidJsonMessage
- messages.invalidJson
- errorCode (parseJsonOrThrow caller-supplied)
- invalid_crontab_number
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/9ac340e9f780fb80.
Report an issue: GitHub.