{"record":{"id":"29422c89c7360e30","repo":"nautechsystems/nautilus_trader","slug":"invalid-hash-index-payload-for-index-key-expe","errorCode":null,"errorMessage":"Invalid hash index payload for '{index_key}': expected field-value pairs","messagePattern":"Invalid hash index payload for '(.+?)': expected field-value pairs","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/infrastructure/src/redis/cache.rs","lineNumber":982,"sourceCode":"        INDEX_ORDER_IDS\n        | INDEX_ORDERS\n        | INDEX_ORDERS_OPEN\n        | INDEX_ORDERS_CLOSED\n        | INDEX_ORDERS_EMULATED\n        | INDEX_ORDERS_INFLIGHT\n        | INDEX_POSITIONS\n        | INDEX_POSITIONS_OPEN\n        | INDEX_POSITIONS_CLOSED => {\n            insert_set(pipe, key, value[0].as_ref());\n            Ok(())\n        }\n        INDEX_ORDER_POSITION => {\n            insert_hset(pipe, key, value[0].as_ref(), value[1].as_ref());\n            Ok(())\n        }\n        INDEX_ORDER_CLIENT => {\n            if !value.len().is_multiple_of(2) {\n                anyhow::bail!(\n                    \"Invalid hash index payload for '{index_key}': expected field-value pairs\"\n                );\n            }\n\n            let entries = value\n                .as_chunks::<2>()\n                .0\n                .iter()\n                .map(|entry| (entry[0].as_ref(), entry[1].as_ref()))\n                .collect::<Vec<(&[u8], &[u8])>>();\n            pipe.hset_multiple(key, &entries);\n            Ok(())\n        }\n        _ => anyhow::bail!(\"Index unknown '{index_key}' on insert\"),\n    }\n}\n\nfn insert_string(pipe: &mut Pipeline, key: &str, value: &[u8]) {","sourceCodeStart":964,"sourceCodeEnd":1000,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/infrastructure/src/redis/cache.rs#L964-L1000","documentation":"insert_index in the Redis cache adapter validates that the payload for INDEX_ORDER_CLIENT (an HSET index) contains an even number of byte slices so they can be paired as hash field-value entries. When the value slice length is not a multiple of 2, it cannot form field-value pairs, so the insert is rejected with this error before any Redis command is issued. It prevents silently writing a truncated or mispaired hash.","triggerScenarios":"Calling cache.insert with an index key of INDEX_ORDER_CLIENT where the `value: &[Bytes]` argument has an odd number of elements (e.g. only the client_order_id field without its value, or an extra stray element).","commonSituations":"Serialization/persistence code that appends index fields one at a time but drops the last value; a caller updated to add a new field pair but only partially writing it; hand-built payloads in custom adapters or test harnesses misaligning field/value ordering.","solutions":["Inspect the caller's `value` construction for the order-client index and ensure every field is immediately followed by its value (even element count).","Log/print value.len() and each element at the call site to find the unpaired element.","If a field is optional, pass both field and value (e.g. empty value) rather than omitting one half of the pair.","Add a unit test asserting the payload length is a multiple of 2 before calling insert."],"exampleFix":"// before\nlet value = vec![client_order_id_bytes]; // odd: field without value\ninsert_index(pipe, key, value, INDEX_ORDER_CLIENT)?;\n// after\nlet value = vec![client_order_id_bytes, order_id_bytes]; // field-value pair\ninsert_index(pipe, key, value, INDEX_ORDER_CLIENT)?;","handlingStrategy":"validation","validationCode":"// Rust\nif value.len() % 2 != 0 {\n    return Err(anyhow::anyhow!(\n        \"order-client index payload must contain field-value pairs; got {} elements\",\n        value.len()\n    ));\n}","typeGuard":null,"tryCatchPattern":"// Python bindings\ntry:\n    cache.insert(index_key, key, payload)\nexcept RuntimeError as e:\n    if \"expected field-value pairs\" in str(e):\n        log.error(\"Mispaired index payload: %s\", payload)\n    else:\n        raise","preventionTips":["Always build index payloads as explicit (field, value) tuples before flattening.","Assert payload length is even in unit tests for index writes.","Never append index fields conditionally without their values; use empty values for optional fields."],"tags":["redis","cache","validation","payload-format"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}