From 0f92317abb0c38cb4809f2559560f6063e8e1139 Mon Sep 17 00:00:00 2001 From: sysops Date: Sun, 12 Jul 2026 17:55:37 +0200 Subject: [PATCH] Fix "no such file or directory" on first use of new collections scribble.ReadAll only returns its own ErrMissingCollection when the collection name is empty - when the collection's directory simply doesn't exist yet (e.g. before the first firewall rule or IP list entry is ever created), it returns a raw os.IsNotExist error instead, which GetFirewallRules/GetIPListEntries/GetServers didn't handle, surfacing as "open db/ip_list_entries: no such file or directory" on a fresh install. New isMissingCollectionErr() helper treats both cases as "empty collection", not a real failure. Co-Authored-By: Claude Sonnet 5 --- store/jsondb/jsondb.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/store/jsondb/jsondb.go b/store/jsondb/jsondb.go index 3bebf7f..765cb0b 100644 --- a/store/jsondb/jsondb.go +++ b/store/jsondb/jsondb.go @@ -555,7 +555,7 @@ func (o *JsonDB) GetServers() ([]model.Server, error) { var servers []model.Server results, err := o.conn.ReadAll("servers") if err != nil { - if err == scribble.ErrMissingCollection { + if isMissingCollectionErr(err) { return servers, nil } return servers, err @@ -570,6 +570,17 @@ func (o *JsonDB) GetServers() ([]model.Server, error) { return servers, nil } +// isMissingCollectionErr reports whether err from scribble.ReadAll just +// means "this collection doesn't exist yet" (nothing written there so +// far). scribble only returns its own ErrMissingCollection when the +// collection name itself is empty - if the collection's directory simply +// hasn't been created yet, ReadAll instead returns a raw os.IsNotExist +// error, which must be treated the same way (empty collection, not a +// real failure). +func isMissingCollectionErr(err error) bool { + return err == scribble.ErrMissingCollection || os.IsNotExist(err) +} + // validateServerID checks a server ID before it is ever used as a jsondb // record key, shared by every server-scoped store method below. func validateServerID(serverID string) error { @@ -686,7 +697,7 @@ func (o *JsonDB) GetFirewallRules(serverID string) ([]model.FirewallRule, error) rules := make([]model.FirewallRule, 0) records, err := o.conn.ReadAll("firewall_rules") if err != nil { - if err == scribble.ErrMissingCollection { + if isMissingCollectionErr(err) { return rules, nil } return nil, err @@ -742,7 +753,7 @@ func (o *JsonDB) GetIPListEntries() ([]model.IPListEntry, error) { entries := make([]model.IPListEntry, 0) records, err := o.conn.ReadAll("ip_list_entries") if err != nil { - if err == scribble.ErrMissingCollection { + if isMissingCollectionErr(err) { return entries, nil } return nil, err