{"record":{"id":"7a3717f65fe640a3","repo":"quickwit-oss/quickwit","slug":"read-only","errorCode":null,"errorMessage":"read-only","messagePattern":"read-only","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-directories/src/lib.rs","lineNumber":44,"sourceCode":"\nmod bundle_directory;\nmod caching_directory;\nmod debug_proxy_directory;\nmod hot_directory;\nmod storage_directory;\nmod union_directory;\n\npub use self::bundle_directory::{BundleDirectory, get_hotcache_from_split, read_split_footer};\npub use self::caching_directory::CachingDirectory;\npub use self::debug_proxy_directory::{DebugProxyDirectory, ReadOperation};\npub use self::hot_directory::{HotDirectory, write_hotcache};\npub use self::storage_directory::StorageDirectory;\npub use self::union_directory::UnionDirectory;\n\nmacro_rules! read_only_directory {\n    () => {\n        fn atomic_write(&self, _path: &Path, _data: &[u8]) -> io::Result<()> {\n            unimplemented!(\"read-only\")\n        }\n\n        fn delete(&self, _path: &Path) -> Result<(), tantivy::directory::error::DeleteError> {\n            unimplemented!(\"read-only\")\n        }\n\n        fn open_write(\n            &self,\n            _path: &Path,\n        ) -> Result<tantivy::directory::WritePtr, tantivy::directory::error::OpenWriteError> {\n            unimplemented!(\"read-only\")\n        }\n\n        fn sync_directory(&self) -> io::Result<()> {\n            unimplemented!(\"read-only\")\n        }\n\n        fn watch(","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-directories/src/lib.rs#L26-L62","documentation":"The read_only_directory! macro in quickwit-directories provides a default `atomic_write` implementation for read-only tantivy Directory wrappers (e.g. StorageDirectory, UnionDirectory). Calling atomic_write on such a directory always aborts with unimplemented!(\"read-only\") — writes are structurally impossible by design on these directories.","triggerScenarios":"Any code path that attempts `directory.atomic_write(path, data)` on a directory created via read_only_directory! (e.g. a StorageDirectory over S3 used for search).","commonSituations":"Tantivy trying to write hotspot metadata or a deleted-bitset during a search on a read-only split; accidentally pointing a component that needs writes at a read-only directory implementation.","solutions":["Use a writable directory (e.g. ManagedDirectory with its storage, or a temp-dir directory) for any code path that writes.","Restructure the code so read-only directories are only used for open/read operations.","If you only need an in-memory write target, wrap with caching/BoundingBoxDirectory semantics or RAMDirectory."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// ensure the directory supports writes before calling:\nfn supports_write<D: Directory>(dir: &D) -> bool {\n    std::any::type_name_of_val(dir).contains(\"StorageDirectory\") == false // read-only macro users\n}","typeGuard":"trait WritableDirectory: Directory {}\nfn require_writable(dir: &dyn Directory) -> Option<&dyn WritableDirectory> {\n    // narrow via downcast to the managed/writable impl\n    dir.as_any().downcast_ref::<ManagedDirectory>().map(|d| d as _)\n}","tryCatchPattern":"// unimplemented! panics; cannot be caught as an io::Error. Guard by design:\nif writable_dir_for(path).is_none() { bail!(\"directory is read-only\"); }","preventionTips":["Never route write operations (hotcache writes, delete-bitsets) through StorageDirectory/UnionDirectory.","Keep a compile-time separation between reader (read-only) and writer (ManagedDirectory) directory types.","Audit custom Directory impls for the read_only_directory! macro before wiring them into write paths."],"tags":["panic","unimplemented","read-only","directory","tantivy"],"backgroundTag":"method-not-implemented","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}