{"record":{"id":"b732ea916f003cc6","repo":"gastownhall/beads","slug":"write-proxy-secret-w","errorCode":null,"errorMessage":"write proxy secret: %w","messagePattern":"write proxy secret: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/server.go","lineNumber":239,"sourceCode":"\t}\n\n\taddr := fmt.Sprintf(\"127.0.0.1:%d\", p.port)\n\n\tln, err := net.Listen(\"tcp\", addr)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"listen on %s: %w\", addr, err)\n\t}\n\n\tp.listener = ln\n\tdefer func() { _ = ln.Close() }()\n\tp.stats.IncListenAndServe()\n\tdataPort, ok := ln.Addr().(*net.TCPAddr)\n\tif !ok {\n\t\treturn fmt.Errorf(\"proxy: unexpected data listener address %T\", ln.Addr())\n\t}\n\n\tif _, err := identity.WriteSecret(p.rootDir); err != nil {\n\t\treturn fmt.Errorf(\"write proxy secret: %w\", err)\n\t}\n\n\tvar identMu sync.RWMutex\n\tidentReply := identity.IdentReply{\n\t\tSchema:   pidfile.SchemaV2,\n\t\tRole:     pidfile.KindProxy,\n\t\tDataPort: dataPort.Port,\n\t}\n\tcontrol, err := startControl(p.rootDir, func() identity.IdentReply {\n\t\tidentMu.RLock()\n\t\tdefer identMu.RUnlock()\n\t\treturn identReply\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"start control listener: %w\", err)\n\t}\n\tdefer func() { _ = control.Close() }()\n","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/server.go#L221-L257","documentation":"Wraps a failure from identity.WriteSecret(p.rootDir), which persists the shared proxy secret file under the database root directory. The control-plane authentication protocol needs this secret on disk before the proxy can serve; if writing it fails, startup aborts with this wrapped error.","triggerScenarios":"ListenAndServe -> identity.WriteSecret returns an error, typically due to filesystem permission problems, a read-only mount, or rootDir not existing.","commonSituations":"Database directory owned by a different user after switching service accounts; disk full; rootDir created by a previous run with restrictive permissions; running on a read-only container volume; macOS/Windows path permission quirks.","solutions":["Check permissions on rootDir and ensure the proxy process user can create/write files there (chown/chmod)","Verify the filesystem is writable (not read-only) and has free space","Confirm rootDir exists and is a directory before starting the proxy","Remove a stale/corrupt secret file if one exists and retry"],"exampleFix":"// before\n_ = os.MkdirAll(rootDir, 0o755) // wrong owner, write fails at runtime\n// after\nif err := os.MkdirAll(rootDir, 0o700); err != nil { return err }\n// ensure the running user owns rootDir before ListenAndServe","handlingStrategy":"validation","validationCode":"// Before ListenAndServe, verify rootDir is writable\nif err := os.MkdirAll(rootDir, 0o700); err != nil { return err }\ntest := filepath.Join(rootDir, \".write-test\")\nif err := os.WriteFile(test, nil, 0o600); err != nil {\n    return fmt.Errorf(\"rootDir not writable: %w\", err)\n}\nos.Remove(test)","typeGuard":null,"tryCatchPattern":"if err := p.ListenAndServe(ctx); err != nil {\n    if errors.Is(err, fs.ErrPermission) {\n        log.Fatalf(\"cannot write proxy secret: check ownership of %s\", rootDir)\n    }\n    log.Fatal(err)\n}","preventionTips":["Run the proxy as the same user that owns rootDir","Provision rootDir with 0700 before first start","Monitor disk space and avoid read-only mounts for the data directory"],"tags":["filesystem","permissions","identity","secret"],"backgroundTag":"file-write-permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}