{"record":{"id":"d56e1e384b9501fb","repo":"RyanCodrai/turbovec","slug":"e","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"turbovec/src/id_map.rs","lineNumber":603,"sourceCode":"    /// - If any query coordinate is non-finite or has magnitude `>= 1e16`.\n    ///\n    /// This is the panicking form, matching\n    /// [`TurboQuantIndex::search`](crate::TurboQuantIndex::search). Use\n    /// [`Self::search_with_allowlist`] with `allowlist = None` for the\n    /// same search as a `Result`. Neither condition can fire on an index\n    /// with no committed `dim` — that case returns the empty result\n    /// before any validation.\n    pub fn search(&self, queries: &[f32], k: usize) -> (Vec<f32>, Vec<u64>) {\n        // Passing `None` rules out the two allowlist variants, but not\n        // the query-shape ones, which `search_with_allowlist` now\n        // returns rather than letting escape as a panic from inside\n        // (#412). So this cannot be an `.expect` on \"cannot fail\": it\n        // re-panics with the error's `Display`, exactly as\n        // `TurboQuantIndex::search_with_mask` does, which keeps the\n        // payload the descriptive message it has always been instead of\n        // burying it behind a `Debug` rendering.\n        self.search_with_allowlist(queries, k, None)\n            .unwrap_or_else(|e| panic!(\"{e}\"))\n    }\n\n    /// Search restricted to the given `allowlist` of external ids.\n    ///\n    /// `allowlist`, when `Some`, restricts the returned top-`k` to ids in the\n    /// allowlist. The allowlist is deduplicated: the effective result count\n    /// per query is `min(k, number of unique ids in allowlist)`, so repeated\n    /// ids don't widen the result.\n    ///\n    /// Returns [`SearchError::AllowlistEmpty`] if `allowlist` is `Some`\n    /// and empty, or [`SearchError::UnknownId`] if it contains an id not\n    /// currently present in the index. Duplicate ids in the allowlist are\n    /// accepted and deduplicated.\n    ///\n    /// The query-shape conditions are reported the same way: a `queries`\n    /// length that is not a whole multiple of the index dim yields\n    /// [`SearchError::QueryBufferNotMultipleOfDim`], and a non-finite or\n    /// out-of-range coordinate yields [`SearchError::InvalidQueryValue`].","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/RyanCodrai/turbovec/blob/ccab9f325e6ce2a270a87daf01ae4e443bcf2d49/turbovec/src/id_map.rs#L585-L621","documentation":"TurboQuantIndex::search is the panicking wrapper around search_with_allowlist: on any search error (e.g. invalid query values or a query buffer whose length is not a multiple of dim) it re-panics with the error's Display message. The panic intentionally preserves the descriptive payload instead of hiding it behind a Debug render.","triggerScenarios":"Calling search(queries, k) where queries contains NaN/inf or |value| >= 1e16 coordinates, or where queries.len() is not a multiple of the index dimension (any SearchError variant from try_search_with_mask / try_search_with_allowlist).","commonSituations":"Feeding unnormalized or corrupted embedding vectors into search; batching queries by concatenating buffers and leaving a partial vector at the end; dimension mismatch between the index and query model.","solutions":["Use try_search_with_allowlist (the Result-returning form) and handle the error instead of panicking.","Validate queries before searching: all coords finite and |v| < 1e16, and queries.len() % dim == 0.","Fix the upstream producer of the query vectors (embedding model or batching code) so buffers are complete and finite."],"exampleFix":"// before\nlet results = index.search(&queries, 10); // panics on bad input\n// after\nmatch index.try_search_with_allowlist(&queries, 10, None) {\n    Ok(r) => /* use r */,\n    Err(e) => eprintln!(\"bad query batch: {e}\"),\n}","handlingStrategy":"try-catch","validationCode":"assert queries.chunks(dim).all(|c| c.len() == dim);\nassert!(queries.iter().all(|v| v.is_finite() && v.abs() < 1e16));","typeGuard":"fn valid_queries(q: &[f32], dim: usize) -> bool {\n    q.len() % dim == 0 && q.iter().all(|v| v.is_finite() && v.abs() < 1e16)\n}","tryCatchPattern":"// Rust: prefer the Result API instead of catching panics\nmatch index.try_search_with_allowlist(&queries, k, None) {\n    Ok(res) => res,\n    Err(e) => { log::error!(\"search failed: {e}\"); Vec::new() }\n}","preventionTips":["Use try_search_* variants in production paths; reserve panicking search for tests.","Validate query buffers are dim-aligned before batch search.","Sanitize embeddings (finite, |v| < 1e16) at ingestion of the query pipeline."],"tags":["rust","panic","vector-search","invalid-input"],"backgroundTag":"invalid-argument-value","analyzedSha":"ccab9f325e6ce2a270a87daf01ae4e443bcf2d49","analyzedAt":"2026-09-06T08:39:18.516Z","contentChangedAt":"2026-09-06T08:39:18.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}