From 45ba71a18993f254f65fdd9a17c43d91dc700850 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 21 Apr 2026 14:52:59 -0700 Subject: [PATCH] fix(volume): write state.pb into a real dir when -dir.idx is unset (#9178) * fix(volume): write state.pb into a real dir when -dir.idx is unset When -dir.idx is not set, NewStore passed the empty default to NewState, making the state.pb path resolve to a relative "state.pb" against the process CWD. Under systemd (where CWD is typically /), this caused "open state.pb: permission denied" for operations such as `volumeServer.state -maintenanceOn`, even though the configured user owned the data dirs. Fall back to the first disk location's IdxDirectory so state.pb lives next to the volume data, consistent with other per-server artifacts. Fixes #9173 * fix(volume): always resolve state.pb dir via first disk location Use s.Locations[0].IdxDirectory unconditionally when a location exists so state.pb inherits the same resolution (~ expansion and empty-idxFolder fallback) already applied for the .idx files. Fall back to util.ResolvePath(idxFolder) in the location-less case so a relative or tilde-prefixed -dir.idx is still normalized. Addresses PR feedback on #9178. --- weed/storage/store.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/weed/storage/store.go b/weed/storage/store.go index 43d3abf29..09bc6dd65 100644 --- a/weed/storage/store.go +++ b/weed/storage/store.go @@ -154,8 +154,17 @@ func NewStore( } wg.Wait() + // Resolve state.pb's directory via the first disk location so it inherits + // the same `~` expansion and empty-idxFolder fallback used for .idx files, + // and is never written as a relative path against the process CWD (#9173). + stateDir := idxFolder + if len(s.Locations) > 0 { + stateDir = s.Locations[0].IdxDirectory + } else if stateDir != "" { + stateDir = util.ResolvePath(stateDir) + } var err error - s.State, err = NewState(idxFolder) + s.State, err = NewState(stateDir) if err != nil { glog.Fatalf("failed to resolve state for volume %s: %v", id, err) }