gastownhall/beads · error
proxy.ForceStopUnverified: publish stop epoch: %w
Error message
proxy.ForceStopUnverified: publish stop epoch: %w
What it means
ForceStopUnverified publishes a stop epoch to coordinate force-stop attempts, and this error wraps any failure of advanceStopEpoch (e.g. inability to write the epoch file in the database root). It is thrown before any process is signaled, aborting the force-stop so concurrent stop attempts do not proceed uncoordinated.
Source
Thrown at internal/storage/dbproxy/proxy/force_stop.go:68
// the record is unchanged. Both flows accept an already-gone recorded
// process. An unverified live PID is never signaled unless its executable
// basename is exactly bd or dolt (with an optional .exe suffix) AND its
// command line scopes it to this workspace; where the platform cannot
// establish that scope, force-stop refuses rather than guessing.
func ForceStopUnverified(rootDir string, opts ...ForceStopOptions) (ForceStopReport, error) {
report := ForceStopReport{RecordPath: pidfile.Path(rootDir, PIDFileName)}
if len(opts) > 1 {
return report, errors.New("proxy.ForceStopUnverified: at most one options value is allowed")
}
timeout := shutdownConfirmDeadline
if len(opts) == 1 && opts[0].Timeout != 0 {
timeout = opts[0].Timeout
}
if timeout <= 0 {
return report, fmt.Errorf("proxy.ForceStopUnverified: timeout must be positive, got %s", timeout)
}
if err := advanceStopEpoch(rootDir); err != nil {
return report, fmt.Errorf("proxy.ForceStopUnverified: publish stop epoch: %w", err)
}
proxyErr := forceStopRecord(rootDir, LockFileName, PIDFileName, pidfile.KindProxy, timeout, &report)
backendReport := ForceStopReport{RecordPath: pidfile.Path(rootDir, server.PIDFileName)}
backendErr := forceStopRecord(
rootDir,
server.LockFileName,
server.PIDFileName,
pidfile.KindDoltBackend,
timeout,
&backendReport,
)
if backendReport.RecordFound || backendErr != nil {
report.Backend = &backendReport
}
return report, errors.Join(proxyErr, backendErr)
}View on GitHub (pinned to 71377f2769)
Solutions
- Verify rootDir exists and is writable by the current user (ls -ld, touch a test file)
- Check the wrapped cause (%w) for the underlying os.MkdirAll/WriteFile error and fix permissions or free disk space accordingly
- Pass the correct workspace root directory path to ForceStopUnverified
- Re-run after the filesystem becomes writable (e.g. remount rw)
Example fix
// before
report, err := proxy.ForceStopUnverified(rootDir)
// after
if info, statErr := os.Stat(rootDir); statErr != nil || !info.IsDir() {
return fmt.Errorf("workspace root %s is not an accessible directory", rootDir)
}
report, err := proxy.ForceStopUnverified(rootDir) Defensive patterns
Strategy: validation
Validate before calling
func rootWritable(dir string) error {
info, err := os.Stat(dir)
if err != nil {
return err
}
if !info.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}
return unix.Access(dir, unix.W_OK)
} Try / catch
report, err := proxy.ForceStopUnverified(rootDir)
if err != nil && strings.Contains(err.Error(), "publish stop epoch") {
fmt.Fprintf(os.Stderr, "check %s is writable: %v\n", rootDir, err)
return err
} Prevention
- Verify the workspace root exists and is writable before force-stop
- Avoid read-only or disk-full filesystems for active databases
- Keep the epoch/state files owned by the running user
- Pass the exact workspace root, not a parent or child path
When it happens
Trigger: Calling proxy.ForceStopUnverified when advanceStopEpoch(rootDir) fails — typically a read-only or missing rootDir, permission denied writing the epoch file, or an I/O error on the filesystem holding the workspace.
Common situations: Running against a database directory mounted read-only, a wrong rootDir path that does not exist, disk-full conditions, or a container running as a different UID than the directory owner.
Related errors
- proxy.ForceStopUnverified: probe %s: %w
- dolt path is not executable
- failed to create backup directory: %w
- failed to create temp file: %w
- create beads directory: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f8a525bc91d7d48c.
Report an issue: GitHub.