gastownhall/beads · error

server: DoltServer.Start: write pidfile: %w

Error message

server: DoltServer.Start: write pidfile: %w

What it means

Start() spawned dolt successfully but failed to write the pidfile (proxy-child.pid) containing pid, port, birth identity and root ID. The pidfile lets other processes discover and validate the managed server, so Start aborts: the child is killed and all state rolled back.

Source

Thrown at internal/storage/dbproxy/server/doltserver.go:301

		cancel()
		lock.Unlock()
		return fmt.Errorf("server: DoltServer.Start: resolve proxy root identity: %w", err)
	}

	if err := pidfile.Write(s.rootDir, PIDFileName, pidfile.PidFile{
		Pid:    s.pid,
		Port:   s.config.Port(),
		Schema: pidfile.SchemaV2,
		Kind:   pidfile.KindDoltBackend,
		Birth:  string(birth),
		RootID: rootID,
	}); err != nil {
		_ = cmd.Process.Kill()
		_, _ = cmd.Process.Wait()
		s.eg, s.egCtx, s.cancel, s.pid = nil, nil, nil, 0
		cancel()
		lock.Unlock()
		return fmt.Errorf("server: DoltServer.Start: write pidfile: %w", err)
	}

	eg.Go(func() error {
		defer lock.Unlock()
		return cmd.Wait()
	})

	if err := s.waitReady(ctx); err != nil {
		cancel()
		_ = s.eg.Wait()
		s.eg, s.egCtx, s.cancel, s.pid = nil, nil, nil, 0
		_ = pidfile.Remove(s.rootDir, PIDFileName)
		return fmt.Errorf("server: DoltServer.Start: %w", err)
	}
	return nil
}

func (s *DoltServer) waitReady(ctx context.Context) error {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check disk space (df -h) and that rootDir is writable by the current user.
  2. Remove a stale proxy-child.pid (after confirming no dolt sql-server is running) and retry.
  3. Fix ownership: chown the data directory to the user running beads.
  4. Retry Start() once filesystem issues are resolved.

Example fix

// before
srv.Start(ctx) // fails: cannot write proxy-child.pid
// after
// as a one-off fix on the machine:
//   rm -f <rootDir>/proxy-child.pid
//   chown -R $(whoami) <rootDir>
if err := srv.Start(ctx); err != nil {
    log.Fatalf("start server: %v", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure rootDir is writable and disk has free space before Start.
if !isDirWritable(rootDir) {
    return fmt.Errorf("rootDir %s not writable by current user", rootDir)
}
var st syscall.Statfs_t
if err := syscall.Statfs(rootDir, &st); err == nil && st.Bavail*uint64(st.Bsize) < 10<<20 {
    return fmt.Errorf("less than 10MB free on %s; refusing to start", rootDir)
}

Try / catch

if err := srv.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "write pidfile") {
        // clean stale pidfile only if no dolt process is running, then retry
        if noDoltRunning() {
            os.Remove(filepath.Join(rootDir, "proxy-child.pid"))
            return srv.Start(ctx)
        }
        return err
    }
    return err
}

Prevention

When it happens

Trigger: pidfile.Write fails — rootDir not writable, disk full, or a conflicting/locked pidfile left over from a prior crash that cannot be overwritten.

Common situations: Read-only or full data volume; permission changes after a previous run (started as root, now running as normal user); stale proxy-child.pid owned by another user in a shared directory.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/c0eb0a344a18b2a8. Report an issue: GitHub.