EpicGames/lore · error · anyhow::Error

Immutable store must be a local store

Error message

Immutable store must be a local store

What it means

GrpcInternalServer::with_components requires the provided immutable store to be a lore_storage::LocalImmutableStore-backed store; if local_immutable_store.is_local() is false it returns this error. The internal gRPC server (node-to-node APIs) only works against local disk storage.

Solutions

  1. Configure a LocalImmutableStore (local disk path) for the internal gRPC server.
  2. If using remote storage, disable the components that require the internal server or use a local cache/staging store alongside it.
  3. Audit the store construction call site to ensure the local store, not the generic one, is passed.

Example fix

// before
let store = Arc::new(S3ImmutableStore::new(...));
GrpcInternalServer::with_components(store, ...)
// after
let store = Arc::new(LocalImmutableStore::new("/data/lore"));
GrpcInternalServer::with_components(store, ...)
Defensive patterns

Strategy: validation

Validate before calling

if !local_immutable_store.is_local() {
    return Err("internal gRPC server requires a LocalImmutableStore");
}

Try / catch

match GrpcInternalServer::with_components(...) {
    Err(e) if e.to_string() == "Immutable store must be a local store" => {
        // switch config to a local-disk store or disable internal server
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling GrpcInternalServer::with_components with a non-local immutable store (e.g. S3/remote object-store implementation) passed as local_immutable_store.

Common situations: Deployments configured with a remote/cloud storage backend but still launching the internal gRPC server; wiring the wrong Arc<dyn ImmutableStore> into with_components; config switched from local disk to object storage without disabling internal server features that require locality.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13). Data as JSON: /api/errors/4aba4e3d5c2874c5. Report an issue: GitHub.

Appendix: source

Thrown at lore-server/src/grpc/grpc_internal_server.rs:87

pub struct WantsComponents(());

impl GrpcInternalServerBuilder<WantsComponents> {
    pub fn new() -> Self {
        Self(WantsComponents(()))
    }

    pub fn with_components(
        self,
        local_immutable_store: Arc<dyn ImmutableStore>,
        immutable_store: Arc<dyn ImmutableStore>,
        mutable_store: Arc<dyn MutableStore>,
        notification_sender: Arc<dyn NotificationSender>,
        hook_dispatcher: Arc<HookDispatcher>,
        environment: EnvironmentConfig,
    ) -> anyhow::Result<GrpcInternalServerBuilder<WantsTlsConfig>> {
        if !local_immutable_store.is_local() {
            return Err(anyhow!("Immutable store must be a local store"));
        }

        Ok(GrpcInternalServerBuilder(WantsTlsConfig {
            local_immutable_store,
            immutable_store,
            mutable_store,
            notification_sender,
            hook_dispatcher,
            environment,
        }))
    }
}

pub struct WantsTlsConfig {
    local_immutable_store: Arc<dyn ImmutableStore>,
    immutable_store: Arc<dyn ImmutableStore>,
    mutable_store: Arc<dyn MutableStore>,
    notification_sender: Arc<dyn NotificationSender>,

View on GitHub (pinned to 074eb0b0d1)