{"record":{"id":"28f529023b31609a","repo":"gastownhall/beads","slug":"open-proxy-log-q-w","errorCode":null,"errorMessage":"open proxy log %q: %w","messagePattern":"open proxy log %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/server.go","lineNumber":148,"sourceCode":"\t\treturn fmt.Errorf(\"clear proxy spawn marker: %w\", err)\n\t}\n\n\t// Fast-abort: a concurrent `bd dolt stop` advances the stop epoch before\n\t// waiting (briefly) for proxy.lock, so an epoch that moved between the\n\t// spawning parent's read and this child taking the lock dooms this start.\n\t// Abort before opening any listener or booting the backend: the stopper\n\t// then observes a free lock within milliseconds instead of after a full\n\t// doomed boot-and-teardown cycle.\n\tif changed, err := stopEpochChanged(p.rootDir, p.stopEpoch); err != nil {\n\t\treturn fmt.Errorf(\"check proxy stop epoch after acquiring %s: %w\", LockFileName, err)\n\t} else if changed {\n\t\treturn fmt.Errorf(\"%w for %s: stop epoch advanced before startup\", errStartInterrupted, p.rootDir)\n\t}\n\n\tlogPath := filepath.Join(p.rootDir, LogFileName)\n\tf, err := os.OpenFile(logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o600) // #nosec G304 -- logPath is derived from operator-supplied config, not untrusted request input\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open proxy log %q: %w\", logPath, err)\n\t}\n\tp.logger = log.New(f, \"[proxy] \", log.LstdFlags|log.Lmicroseconds)\n\tdefer func() { _ = f.Close() }()\n\n\tctx, cancel := context.WithCancel(parentCtx)\n\tdefer cancel()\n\n\t// Install signal handlers BEFORE Listen. Without this, Go's default\n\t// SIGTERM action terminates the process during the startup window\n\t// (Listen, pidfile write, backend Start, readiness wait), bypassing all\n\t// deferred cleanup including RemoveDatabaseProxyPidFile.\n\tsigCh := make(chan os.Signal, 1)\n\tsignal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)\n\tdefer signal.Stop(sigCh)\n\n\tvar sigReceived atomic.Bool\n\tgo func() {\n\t\tselect {","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/server.go#L130-L166","documentation":"ListenAndServe opens rootDir/<LogFileName> in append mode for proxy logging; failure is wrapped as 'open proxy log %q: %w'. Without the log file the proxy refuses to start, since operational logging is mandatory for the doomed-start/stop coordination protocol.","triggerScenarios":"Calling ListenAndServe when os.OpenFile(logPath, O_CREATE|O_APPEND|O_WRONLY, 0600) fails — bad path, permissions, disk full, or logPath pointing at a directory.","commonSituations":"Read-only or full filesystem; rootDir permission changed after install; overly restrictive umask or SELinux/AppArmor policy; log file owned by another user.","solutions":["Check the wrapped cause and fix permissions on the log file / rootDir","Free disk space if the filesystem is full","Remove or chown a stale log file owned by a different user"],"exampleFix":"// before\nsudo chown otheruser:otheruser /data/proxy.log\n// after\nsudo chown $(whoami) /data/proxy.log && bd serve --root /data","handlingStrategy":"validation","validationCode":"logPath := filepath.Join(rootDir, LogFileName)\nif f, err := os.OpenFile(logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o600); err != nil {\n  return fmt.Errorf(\"pre-check log open: %w\", err)\n} else { f.Close() }","typeGuard":null,"tryCatchPattern":"if err := p.ListenAndServe(ctx); err != nil {\n  if strings.Contains(err.Error(), \"open proxy log\") { /* fix perms/disk, retry */ }\n  return err\n}","preventionTips":["Keep rootDir writable and monitor free disk space","Don't chown/chmod proxy log files after install","Check SELinux/AppArmor policies for log writes"],"tags":["filesystem","logging","startup"],"backgroundTag":"log-file-open-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}