{"record":{"id":"c38b735f0f45899b","repo":"bevyengine/bevy","slug":"can-only-hash-u64-using-passhasher","errorCode":null,"errorMessage":"can only hash u64 using PassHasher","messagePattern":"can only hash u64 using PassHasher","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/bevy_platform/src/hash.rs","lineNumber":154,"sourceCode":"        PassHasher::default()\n    }\n}\n\n/// A no-op hash that only works on `u64`s. Will panic if attempting to\n/// hash a type containing non-u64 fields.\n#[derive(Debug, Default)]\npub struct PassHasher {\n    hash: u64,\n}\n\nimpl Hasher for PassHasher {\n    #[inline]\n    fn finish(&self) -> u64 {\n        self.hash\n    }\n\n    fn write(&mut self, _bytes: &[u8]) {\n        panic!(\"can only hash u64 using PassHasher\");\n    }\n\n    #[inline]\n    fn write_u64(&mut self, i: u64) {\n        self.hash = i;\n    }\n}\n\n/// [`BuildHasher`] for types that already contain a high-quality hash.\n#[derive(Clone, Default)]\npub struct NoOpHash;\n\nimpl BuildHasher for NoOpHash {\n    type Hasher = NoOpHasher;\n\n    fn build_hasher(&self) -> Self::Hasher {\n        NoOpHasher(0)\n    }","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_platform/src/hash.rs#L136-L172","documentation":"`PassHasher` (crates/bevy_platform/src/hash.rs) is a pass-through hasher for keys that are already well-distributed u64 values (bevy `Entity` ids). It only implements `write_u64` (stores the value) and `finish`; hashing anything that emits raw bytes hits `write`, which panics with \"can only hash u64 using PassHasher\". Hashers built on it (e.g. `NoOpHash`/the Entity-hash state used by `EntityHashMap`/`EntityHashSet`) are only valid for keys whose `Hash` impl is exactly one `write_u64` call.","triggerScenarios":"Inserting/looking up with a key type that hashes via bytes or non-u64 integers in a map built on this hasher: `&str`, `String`, `u32` (default `write_u32` forwards to `write`), tuples like `(Entity, u32)`, floats, enums, or any composite type. Copying an `EntityHashMap` declaration and swapping the key type is the classic trigger.","commonSituations":"Refactoring an `EntityHashMap<Entity, T>` into a keyed cache with a different key; using the bevy_platform hash state in a `hashbrown`/`HashMap` generic over `S` and instantiating it with non-Entity keys; serialization code storing string keys in an Entity-keyed map.","solutions":["Keep pass-through hashers for `Entity`/`u64` keys only","For arbitrary keys, use a real hasher: std's `RandomState`, or bevy_platform's ahash-based `RandomState`/`FixedState`","If you must keep the map, pre-hash your key to a u64 yourself and use the hash as the key"],"exampleFix":"// before: &str keys in a pass-through-hashed map -> panic on first insert\nlet mut map: EntityHashMap<String, u32> = EntityHashMap::default();\nmap.insert(\"player\".to_string(), 1);\n\n// after: regular hasher for string keys\nlet mut map: HashMap<String, u32> = HashMap::default();\n// or keep EntityHashMap only for Entity/u64 keys","handlingStrategy":"type-guard","validationCode":"null","typeGuard":"/// Only types whose Hash impl is exactly one write_u64 may live in\n/// pass-through-hashed maps. Restrict usage via this newtype.\nstruct EntityMap<V> {\n    inner: EntityHashMap<Entity, V>,\n}\n\nimpl<V> EntityMap<V> {\n    fn insert(&mut self, k: Entity, v: V) -> Option<V> {\n        self.inner.insert(k, v) // Entity -> write_u64, safe\n    }\n    fn get(&self, k: Entity) -> Option<&V> { self.inner.get(&k) }\n}","tryCatchPattern":null,"preventionTips":["Treat EntityHashMap/EntityHashSet as Entity-only containers; use std/ahash maps for any other key","Remember even u32/i32 keys are unsafe here: the default write_u32 forwards to write()","When refactoring map key types, switch the hasher back to RandomState in the same commit"],"tags":["bevy","hashing","hashmap","entity","panic","collections"],"backgroundTag":"incompatible-hash-key-type","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}