GraphiteEditor/Graphite · error
Resource storage not initialized
Error message
Resource storage not initialized
What it means
ResourceStorageMessageHandler wraps an Option<Arc<dyn ResourceStorage>>; resources() clones it with .expect("Resource storage not initialized"). The non-test Default impl deliberately constructs Self { storage: None } (tests get a HashMapResourceStorage instead), so this panic fires exactly when resources() is called on a default-constructed handler - i.e., the editor was wired up without ever providing a resource storage backend. The sibling process_message handles the None case gracefully, so only these accessor call sites panic.
Source
Thrown at editor/src/messages/resource_storage/resource_storage_message_handler.rs:42
fn garbage_collect(&self, used: &[ResourceHash]) {
self.inner.garbage_collect(used)
}
}
#[derive(ExtractField)]
pub struct ResourceStorageMessageHandler {
storage: Option<Arc<dyn ResourceStorage>>,
}
impl ResourceStorageMessageHandler {
pub fn new(resource_storage: Arc<dyn ResourceStorage>) -> Self {
Self { storage: Some(resource_storage) }
}
pub fn resources(&self) -> Box<dyn LoadResource> {
Box::new(ResourcesHandle {
inner: self.storage.clone().expect("Resource storage not initialized"),
})
}
pub fn resources_mut(&self) -> ResourcesHandle {
ResourcesHandle {
inner: self.storage.clone().expect("Resource storage not initialized"),
}
}
}
impl std::fmt::Debug for ResourceStorageMessageHandler {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ResourceStorageMessageHandler").finish_non_exhaustive()
}
}
impl Default for ResourceStorageMessageHandler {
#[cfg(not(test))]View on GitHub (pinned to c507b35645)
Solutions
- Always construct via ResourceStorageMessageHandler::new(storage) at startup so storage is Some from the beginning
- Change resources()/resources_mut() to return Option (or a Result) and let callers skip resource-dependent features when storage is absent
- Log loudly at startup when resource storage is not provided so mis-wiring is visible before any panic
Example fix
// before
pub fn resources(&self) -> Box<dyn LoadResource> {
Box::new(ResourcesHandle { inner: self.storage.clone().expect("Resource storage not initialized") })
}
// after
pub fn resources(&self) -> Option<Box<dyn LoadResource>> {
self.storage.clone().map(|inner| Box::new(ResourcesHandle { inner }) as Box<dyn LoadResource>)
} Defensive patterns
Strategy: validation
Validate before calling
if let Some(storage) = &self.storage {
let handle = ResourcesHandle { inner: storage.clone() };
// use handle
} else {
log::error!("resource storage not initialized; skipping resource feature");
} Type guard
fn is_initialized(handler: &ResourceStorageMessageHandler) -> bool {
handler.storage.is_some()
} Prevention
- Construct the handler with ::new(storage) in every entry point instead of Default
- Make accessors return Option and let callers degrade gracefully
- Log at startup when resource storage is missing so mis-wiring is caught early
When it happens
Trigger: Constructing the handler via Default::default() (as some generic message-handler scaffolding does) and then calling resources(), which dereferences the never-initialized storage.
Common situations: New entry points (CLI, tests, embedded scenarios) building the editor state with Default instead of ResourceStorageMessageHandler::new(storage); refactors that reset the portfolio/message handlers to defaults at runtime.
Related errors
- Failed to initialize on-disk resource storage
- Ungrouped folder must have a parent
- Solidify Stroke node should exist
- In `check_layer()`: there should be a `target`
- Artboard should have a primary input
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/292d118789a0f451.
Report an issue: GitHub.