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 string

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Print the resolved absolute path before loading to catch CWD-relative surprises.
  2. Verify the file exists and is readable by the running user (stat + access check).
  3. Use an absolute path or resolve relative to the executable / a known config dir.
  4. Ensure the deploy artifact actually includes the config file.
  5. 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

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


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/38810891dd2f4992. Report an issue: GitHub.