affaan-m/ECC · error
load config %s: %w
Error message
load config %s: %w
What it means
Wrapped error from LoadConfig in golang-patterns. LoadConfig calls os.ReadFile(path); on any read failure it wraps the error as fmt.Errorf("load config %s: %w", path, err). The message indicates the file at `path` could not be read; the underlying os.PathError (open/read) is preserved for the caller.
Source
Thrown at skills/golang-patterns/SKILL.md:103
return &Result{Data: data}, nil
}
// Bad: Returns interface (hides implementation details unnecessarily)
func ProcessData(r io.Reader) (io.Reader, error) {
// ...
}
```
## Error Handling Patterns
### Error Wrapping with Context
```go
// Good: Wrap errors with context
func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("load config %s: %w", path, err)
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("parse config %s: %w", path, err)
}
return &cfg, nil
}
```
### Custom Error Types
```go
// Define domain-specific errors
type ValidationError struct {
Field string
Message stringView on GitHub (pinned to 01e15490f0)
Solutions
- Print the resolved absolute path before loading to catch CWD-relative surprises.
- Verify the file exists and is readable by the running user (stat + access check).
- Use an absolute path or resolve relative to the executable / a known config dir.
- Ensure the deploy artifact actually includes the config file.
- Fail fast at startup with a clear message rather than letting the wrapped error propagate.
Example fix
// before
cfg, err := LoadConfig(path)
if err != nil {
log.Fatal(err)
}
// after
cfg, err := LoadConfig(path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
log.Fatalf("config file not found at %s; set --config or CONFIG_PATH", path)
}
log.Fatalf("loading config %s: %v", path, err)
} Defensive patterns
Strategy: validation
Validate before calling
func ensureConfigReadable(path string) error {
abs, err := filepath.Abs(path)
if err != nil {
return err
}
info, err := os.Stat(abs)
if err != nil {
return err
}
if info.IsDir() {
return fmt.Errorf("%s is a directory, not a file", abs)
}
if info.Mode().Perm()&0400 == 0 {
return fmt.Errorf("%s is not readable", abs)
}
return nil
} Type guard
func isMissingFile(err error) bool {
return errors.Is(err, fs.ErrNotExist)
}
func isPermissionDenied(err error) bool {
return errors.Is(err, fs.ErrPermission)
} Try / catch
cfg, err := LoadConfig(path)
if err != nil {
if isMissingFile(err) {
log.Fatalf("config not found at %s; set --config", path)
}
if isPermissionDenied(err) {
log.Fatalf("no read permission on %s", path)
}
log.Fatalf("load config: %v", err)
} Prevention
- Resolve the config path to absolute at startup and log it.
- Include the config file in your deploy artifact and verify it in CI.
- Default to a stable, well-known config directory.
- Fail fast at startup instead of letting read errors surface later.
When it happens
Trigger: Calling LoadConfig(path) when os.ReadFile(path) returns a non-nil error. Concrete triggers: the path does not exist (fs.ErrNotExist), permission denied (fs.ErrPermission), a path component is not a directory, or the path is empty.
Common situations: Wrong config path passed at startup (relative path resolved against an unexpected CWD); the file was not included in the container image or deployment artifact; permissions were stripped after a deploy; the env var pointing at the config is unset so path is empty or default.
Related errors
- --config-dir must exist and contain a regular sixtytwo.yaml
- get user %s: %w
- failed to create user: %w
- user %s: %w
- querying user %s: %w
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/38810891dd2f4992.
Report an issue: GitHub.