Abort startup on a config file pixa cannot read (closes #176)
check / check (push) Waiting to run
check / check (push) Waiting to run
Of the places pixa looks for its config file on its own, it passed over any place where os.Stat failed, so a file in a directory pixa may not enter was skipped without a word and pixa started on a later file or on the environment and defaults. Now only a file that does not exist is passed over; any other error aborts startup naming the file, as a file that does not parse already did. README.md says so where it gives the search order. Model: opus-5-5
This commit is contained in:
@@ -354,10 +354,10 @@ pixa finds: `/etc/pixa/config.yml`, `/etc/pixa/config.yaml`,
|
||||
`~/.config/pixa/config.yml`, `~/.config/pixa/config.yaml`, then `config.yml`
|
||||
and `config.yaml` in the working directory. A named file that does not exist,
|
||||
cannot be read or does not parse aborts startup. Of the files pixa looks for on
|
||||
its own, one it finds but cannot read or parse aborts startup; one it cannot
|
||||
find, for any reason, is passed over without a message, even when the file is
|
||||
there in a directory pixa may not enter. With no file, pixa uses the environment
|
||||
and the defaults.
|
||||
its own, only one that does not exist is passed over, without a message. One
|
||||
that pixa cannot read or parse aborts startup, naming the file. So does one in a
|
||||
directory pixa may not enter, whether or not it is there, since pixa cannot
|
||||
tell. With no file, pixa uses the environment and the defaults.
|
||||
|
||||
| Variable | Config key | Meaning |
|
||||
| ------------------------------------ | ------------------------------- | ---------------------------------------------------------------------------- |
|
||||
|
||||
@@ -29,6 +29,11 @@ P2: security: referer blacklist
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-10-04 a config file pixa cannot read aborts startup (closes #176): of the
|
||||
places pixa looks for its config file on its own, only one where the file does
|
||||
not exist is passed over; any other error, such as a directory on the path
|
||||
that pixa may not enter, aborts startup naming the file, as a file that does
|
||||
not parse already did.
|
||||
- 2026-10-04 request IDs returned and passed on, and `/v1/e/` revalidates
|
||||
(closes #84): pixa's own `RequestID` middleware, in place of chi's, gives each
|
||||
request an ID, its own `X-Request-ID` when that is at most 64 letters, digits,
|
||||
|
||||
@@ -4,6 +4,7 @@ package config
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log/slog"
|
||||
"math"
|
||||
"net/netip"
|
||||
@@ -778,10 +779,17 @@ func loadConfigFile(log *slog.Logger, appName string) (*smartconfig.Config, erro
|
||||
for _, path := range configPaths {
|
||||
cleanPath := filepath.Clean(path)
|
||||
|
||||
// Only a config file that does not exist is skipped. One that
|
||||
// cannot be read or does not parse is a fatal startup error.
|
||||
_, statErr := os.Stat(cleanPath)
|
||||
if statErr == nil {
|
||||
// A config file that exists but does not parse is a fatal
|
||||
// startup error, never something to skip over.
|
||||
if errors.Is(statErr, fs.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
|
||||
if statErr != nil {
|
||||
return nil, fmt.Errorf("failed to read config file %s: %w", path, statErr)
|
||||
}
|
||||
|
||||
sc, err := smartconfig.NewFromConfigPath(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config file %s: %w", path, err)
|
||||
@@ -791,7 +799,6 @@ func loadConfigFile(log *slog.Logger, appName string) (*smartconfig.Config, erro
|
||||
|
||||
return sc, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil //nolint:nilnil // nil config is valid (use defaults)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user