gastownhall/beads · error
rotating %s -> %s: %w
Error message
rotating %s -> %s: %w
What it means
rotateLogIfOversized wraps os.Rename(primary, rotated) failures as "rotating %s -> %s: %w". Rename overwrites the destination on both Unix and Windows, so this error means the log could not be moved aside when it exceeded maxBytes — typically a cross-device move, permission problem, or the destination path being occupied in a way Rename cannot replace (e.g. a directory).
Source
Thrown at internal/doltserver/logrotate.go:98
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) {
primary := logPath(beadsDir)
max := maxLogBytes()
rotated, err := rotateLogIfOversized(primary, max)
if err != nil {
debug.Logf("doltserver: log rotation failed for %s: %v", primary, err)
return
}
if rotated {
debug.Logf("doltserver: rotated %s -> %s (exceeded %d bytes)", primary, rotatedLogPath(primary), max)View on GitHub (pinned to 71377f2769)
Solutions
- Check that the rotated path (e.g. server.log.1) is not a directory; remove or rename it.
- Ensure the bd user has write permission on the directory containing the log (needed for rename).
- Move the log directory onto a single filesystem, or delete/move the oversized log manually and restart.
- Copy-then-delete manually if a cross-device rename is unavoidable: cp server.log server.log.1 && rm server.log.
Example fix
// before (broken state) $ ls .beads/logs server.log server.log.1/ # rotated name is a directory // after $ rm -rf .beads/logs/server.log.1 $ bd start # rotation now succeeds
Defensive patterns
Strategy: validation
Validate before calling
rotated := rotatedLogPath(primary)
if info, err := os.Lstat(rotated); err == nil && info.IsDir() {
return fmt.Errorf("%s is a directory; cannot overwrite via rename", rotated)
}
// source and destination must share a device
s1, _ := os.Stat(filepath.Dir(primary))
s2, _ := os.Stat(filepath.Dir(rotated))
if s1 != nil && s2 != nil && !sameDevice(s1, s2) {
return fmt.Errorf("cross-device rename would fail")
} Try / catch
rotated, err := rotateLogIfOversized(primary, maxBytes)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EXDEV) {
// fall back to copy+delete
}
return err
} Prevention
- Keep log and rotated log on the same filesystem
- Never create directories named like the rotated log (e.g. server.log.1)
- Maintain write permission on the log's parent directory
- Prefer built-in rotation instead of external log rotators fighting over the same file
When it happens
Trigger: The primary log exceeds maxBytes and os.Rename to rotatedLogPath(primary) fails: rotated path exists as a directory, source and destination are on different filesystems, or permissions prevent the rename in either directory.
Common situations: An old rotated log file was replaced by a directory of the same name; the log lives in a container volume while the rotated name resolves elsewhere; running bd without write permission on the log directory after a user change.
Related errors
- stat %s: %w
- server: NewDoltServer: failed to determine absolute path of
- failed to rename temp file: %w
- failed to migrate database %s to %s: %w
- retiring sidecar %s -> %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a963d050df774c2e.
Report an issue: GitHub.