gastownhall/beads · error
proxy.ForceStopUnverified: at most one options value is allo
Error message
proxy.ForceStopUnverified: at most one options value is allowed
What it means
ForceStopUnverified accepts variadic ForceStopOptions but is defined to take at most one options value. Passing more than one is a programming error and is rejected up front before any destructive work. This keeps the API contract unambiguous about timeout configuration.
Source
Thrown at internal/storage/dbproxy/proxy/force_stop.go:58
// unverifiable proxy or backend record. It applies the same procedure to the
// proxy record (proxy.pid) and the backend record (proxy-child.pid): a
// pre-v2 managed-local deployment leaves BOTH as legacy records, so covering
// only the proxy record would lock the advertised recovery out of the real
// upgrade topology.
//
// For each record: when its lock is free, the function holds it while
// inspecting, signaling, and quarantining the unchanged record. When the lock
// is held (the usual pre-upgrade-proxy case), it first inspects and signals
// the live PID, waits for the lock to become free, then quarantines only if
// 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,View on GitHub (pinned to 71377f2769)
Solutions
- Pass at most one ForceStopOptions value
- Merge desired fields into a single ForceStopOptions struct
- Call with no options to use the default shutdownConfirmDeadline
Example fix
// before
report, err := proxy.ForceStopUnverified(root, proxy.ForceStopOptions{Timeout: 5 * time.Second}, proxy.ForceStopOptions{})
// after
report, err := proxy.ForceStopUnverified(root, proxy.ForceStopOptions{Timeout: 5 * time.Second}) Defensive patterns
Strategy: validation
Validate before calling
func safeForceStop(root string, opts ...proxy.ForceStopOptions) (proxy.ForceStopReport, error) {
if len(opts) > 1 {
opts = opts[:1]
}
return proxy.ForceStopUnverified(root, opts...)
} Prevention
- Remember ForceStopOptions is a single optional value, not a slice of configs
- Centralize force-stop calls in one helper that normalizes options
- Never spread user-supplied option slices into the call
When it happens
Trigger: Calling proxy.ForceStopUnverified(root, opt1, opt2) with two or more ForceStopOptions values.
Common situations: Copy-paste refactors that append an extra options value; wrapping helpers that spread plus pass an explicit option.
Related errors
- no store is open for this workspace
- not found
- no absolute native user directory is available
- ExternalDoltConfig: set either Socket OR (Host, Port), not b
- ExternalDoltConfig: must set Socket or (Host, Port)
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c3decc64ab6e1562.
Report an issue: GitHub.