EpicGames/lore · error
parsing a ClientIdentify request must succeed
Error message
parsing a ClientIdentify request must succeed
What it means
A Rust test panic from `.expect("parsing a ClientIdentify request must succeed")` on `StorageServiceV4::parse_request_bytes` in `parse_client_identify_opcode_returns_variant` (lore-server/src/quic/storage_service_v4.rs:547). A `ClientIdentify` command header with payload `my-client/1.0` was rejected by the parser, returning a `MessageParseError` instead of `ParsedStorageRequestV4::ClientIdentify(_)`. This indicates the V4 storage parser does not recognize or cannot decode the ClientIdentify opcode/payload as the test framed it.
Solutions
- Print the MessageParseError: `.unwrap_or_else(|e| panic!("parse failed: {e:?}"))` to see if it is unknown-opcode vs payload decode.
- Add/verify the ClientIdentify branch in `parse_request_bytes` in lore-server/src/quic/storage_service_v4.rs so it maps `Command::ClientIdentify` to `ParsedStorageRequestV4::ClientIdentify`.
- Confirm `Command::ClientIdentify`'s discriminant in lore_transport::quic::storage_service matches the opcode the parser dispatches on (no enum reordering drift).
- Match the payload encoding the parser expects (e.g. wrap `my-client/1.0` in the expected length-prefixed/UTF-8 format) or update the parser to accept the documented format.
Example fix
// before
let parsed = service
.parse_request_bytes(&header, payload)
.expect("parsing a ClientIdentify request must succeed");
// after
let parsed = service
.parse_request_bytes(&header, payload)
.unwrap_or_else(|e| panic!("parsing ClientIdentify failed: {e:?}"));
// and in parse_request_bytes:
// Command::ClientIdentify => Ok(ParsedStorageRequestV4::ClientIdentify(
// ClientIdentify::decode(payload)?,
// )) Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the opcode the test sends is one the parser dispatches on let header = make_header(Command::ClientIdentify as u8); assert_ne!(header.opcode, 0, "ClientIdentify discriminant must be non-zero and registered");
Type guard
fn as_client_identify(p: &ParsedStorageRequestV4) -> Option<&ClientIdentify> {
match p {
ParsedStorageRequestV4::ClientIdentify(ci) => Some(ci),
_ => None,
}
} Try / catch
let parsed = service.parse_request_bytes(&header, payload)
.await
.unwrap_or_else(|e| panic!("ClientIdentify parse failed: {e:?}"));
assert!(matches!(parsed, ParsedStorageRequestV4::ClientIdentify(_))); Prevention
- Add a ClientIdentify branch to parse_request_bytes as soon as the Command variant is added.
- Avoid reordering protocol enums; append new opcodes to keep discriminants stable.
- Encode test payloads with the same serializer the parser decodes with.
When it happens
Trigger: Calling `service.parse_request_bytes(&make_header(Command::ClientIdentify as u8), Bytes::from("my-client/1.0"))` where the parser's match on the opcode lacks a ClientIdentify branch, `make_header` builds a header the parser rejects (version/opcode mismatch), or the payload fails ClientIdentify deserialization (e.g. the parser expects a length-prefixed or protobuf-encoded user-agent, not raw bytes).
Common situations: Seen when the ClientIdentify op was newly added to `Command` but `parse_request_bytes` at storage_service_v4.rs:134 wasn't updated, when the wire encoding of the user-agent changed, or when `Command::ClientIdentify as u8` collides with a different opcode after a protocol enum reorder.
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
- handler failed
- ClientIdentify must be handled successfully
- Stream handler factory was not set
- No alpns provided
- Address was not set
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/50b52d8b1d262adf.
Report an issue: GitHub.
Appendix: source
Thrown at lore-server/src/quic/storage_service_v4.rs:547
cmd,
..CommandHeader::default()
}
}
#[tokio::test]
async fn parse_client_identify_opcode_returns_variant() {
use lore_transport::quic::storage_service::Command;
// The stores are unused by parse_request_bytes, so a minimal service suffices.
let (immutable_store, mutable_store, _exec) =
test_store_create().await.expect("Failed to create stores");
let service = make_service(immutable_store, mutable_store);
let header = make_header(Command::ClientIdentify as u8);
let payload = Bytes::from("my-client/1.0");
let parsed = service
.parse_request_bytes(&header, payload)
.expect("parsing a ClientIdentify request must succeed");
assert!(
matches!(parsed, ParsedStorageRequestV4::ClientIdentify(_)),
"expected ClientIdentify variant, got {parsed:?}"
);
}
#[tokio::test]
async fn parse_client_identify_stores_value() {
use lore_transport::quic::storage_service::Command;
let (immutable_store, mutable_store, _exec) =
test_store_create().await.expect("Failed to create stores");
let service = make_service(immutable_store, mutable_store);
let header = make_header(Command::ClientIdentify as u8);
let payload = Bytes::from("my-client/1.0");
let parsed = serviceView on GitHub (pinned to 074eb0b0d1)