gastownhall/beads · error
stat %s: %w
Error message
stat %s: %w
What it means
rotateLogIfOversized wraps os.Stat(primary) failures as "stat %s: %w". A missing log file is deliberately treated as a no-op (returns false, nil); this error is thrown only for other stat failures such as permission problems or I/O errors. It prevents bd from deciding whether the dolt-server log needs rotation.
Source
Thrown at internal/doltserver/logrotate.go:89
//
// Behavior:
// - maxBytes <= 0: rotation disabled, returns (false, nil).
// - primary missing: returns (false, nil). Nothing to rotate.
// - primary size <= maxBytes: returns (false, nil). Leave alone.
// - primary size > maxBytes: rename to <primary>.1 and return (true, nil).
// - rename fails: returns (false, err).
//
// The caller should treat errors as non-fatal and proceed to open the log.
func rotateLogIfOversized(primary string, maxBytes int64) (bool, error) {
if maxBytes <= 0 {
return false, nil
}
info, err := os.Stat(primary)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, fmt.Errorf("stat %s: %w", primary, err)
}
if info.Size() <= maxBytes {
return false, nil
}
rotated := rotatedLogPath(primary)
// os.Rename overwrites the destination on both Unix and Windows (Go's
// Rename wraps MoveFileEx with MOVEFILE_REPLACE_EXISTING on Windows).
if err := os.Rename(primary, rotated); err != nil {
return false, fmt.Errorf("rotating %s -> %s: %w", primary, rotated, err)
}
return true, nil
}
// maybeRotateLog is the convenience wrapper used by Start(). It rotates the
// dolt-server log if it is oversized and emits a debug message on both
// rotation and error paths. It never returns an error — rotation is
// best-effort and must not block server startup.
func maybeRotateLog(beadsDir string) {View on GitHub (pinned to 71377f2769)
Solutions
- Fix permissions on the log file and its directory so the bd user can stat it (chmod/chown).
- Verify the log path's parent directories exist and none of them is a regular file.
- Check disk health / mount state if the error is an I/O error (dmesg, mount output).
- If the path is wrong, correct the server log path configuration and restart.
Example fix
// before
info, err := os.Stat(primary)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, fmt.Errorf("stat %s: %w", primary, err)
}
// after
// ensure the directory is writable by the bd user first:
// sudo chown -R $(whoami) .beads/logs
// then retry the command that started the server Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(filepath.Dir(primary)); err != nil {
return fmt.Errorf("log dir unavailable: %w", err)
}
if f, err := os.OpenFile(primary, os.O_APPEND|os.O_CREATE, 0o644); err == nil {
f.Close()
} Type guard
func logStatOk(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsNotExist(err) // both are safe for rotation
} Try / catch
rotated, err := rotateLogIfOversized(primary, maxBytes)
if err != nil {
if errors.Is(err, fs.ErrPermission) {
log.Printf("cannot rotate log %s: fix permissions", primary)
}
return err
} Prevention
- Ensure the log directory is owned/writable by the bd user
- Avoid running bd as root and then as a normal user on the same workspace
- Check parent path components are directories, not files
- Monitor disk/mount health if logs live on network storage
When it happens
Trigger: maybeRotateLog calls rotateLogIfOversized and os.Stat on the primary dolt-server log fails with something other than NotExist: permission denied on the log directory, an I/O error, or a broken path component (e.g. parent is a file).
Common situations: The .beads/ or log directory was created by another user (root) and bd now runs unprivileged; the log path points across a flaky network mount; filesystem errors on disk-full volumes.
Related errors
- rotating %s -> %s: %w
- dolt path is not executable
- server: NewDoltServer: failed to determine absolute path of
- failed to create backup directory: %w
- failed to create temp file: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/43c22f1d6f5397e2.
Report an issue: GitHub.