{"record":{"id":"a33f0f3e7e2ddf9f","repo":"gastownhall/beads","slug":"resolve-proxy-root-identity-w","errorCode":null,"errorMessage":"resolve proxy root identity: %w","messagePattern":"resolve proxy root identity: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/server.go","lineNumber":288,"sourceCode":"\tif err := waitForServerReady(ctx, p.server, serverReadyTimeout); err != nil {\n\t\tif changed, cerr := stopEpochChanged(p.rootDir, p.stopEpoch); cerr == nil && changed {\n\t\t\treturn abortInterruptedStart()\n\t\t}\n\t\tp.stats.IncBackendStop()\n\t\t_ = stopBackendBounded(p.server)\n\t\treturn fmt.Errorf(\"database server not ready: %w\", err)\n\t}\n\tbirth, err := procid.Capture(os.Getpid())\n\tif err != nil {\n\t\tp.stats.IncBackendStop()\n\t\t_ = stopBackendBounded(p.server)\n\t\treturn fmt.Errorf(\"capture proxy birth identity: %w\", err)\n\t}\n\trootID, err := identity.RootID(p.rootDir)\n\tif err != nil {\n\t\tp.stats.IncBackendStop()\n\t\t_ = stopBackendBounded(p.server)\n\t\treturn fmt.Errorf(\"resolve proxy root identity: %w\", err)\n\t}\n\tupstreamID := p.server.ID(ctx)\n\tidentMu.Lock()\n\tidentReply.RootID = rootID\n\tidentReply.UpstreamID = upstreamID\n\tidentReply.PID = os.Getpid()\n\tidentReply.Birth = string(birth)\n\tidentReply.ControlPort = control.Port()\n\tidentMu.Unlock()\n\n\t// Last fence before publishing: the spawn marker was cleared when this\n\t// process took proxy.lock, so a `bd dolt stop` that began during a slow\n\t// backend start has no record of this attempt. It did advance the stop\n\t// epoch first, so re-check it here and abort instead of publishing a\n\t// running proxy after that stop returned. The startup epoch watcher is\n\t// stopped (synchronously) first: past this fence a stop finds the\n\t// published proxy.pid and stops the proxy through it, so a watcher\n\t// cancellation must not race the publish.","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/server.go#L270-L306","documentation":"Wraps a failure of identity.RootID(p.rootDir), which resolves the stable root identity of the database directory used in the proxy's IdentReply. If the root identity file/record cannot be read or is invalid, the backend is stopped and startup aborts - the proxy refuses to advertise itself without a verifiable root identity.","triggerScenarios":"ListenAndServe -> identity.RootID fails because the root metadata in rootDir is missing, corrupted, was written by an incompatible schema version, or is unreadable due to permissions.","commonSituations":"rootDir initialized by an older/newer beads version (schema drift); partially initialized directory where init was interrupted; manual copy of the database dir that dropped identity files; permission changes after backup/restore.","solutions":["Re-initialize or repair the database root (re-run init) so a valid root identity exists","Restore the missing identity files from a known-good backup of rootDir","Check file permissions on the identity metadata files in rootDir","Confirm the tooling and proxy versions agree on the identity schema"],"exampleFix":"// before\n// identity file missing after manual dir copy\n$ cp -r /data/db /data/db-copy  # dropped hidden identity files\n// after\n$ bd init /data/db-copy  # or restore the full directory including identity metadata","handlingStrategy":"validation","validationCode":"// Confirm the root identity metadata exists before start\nif _, err := os.Stat(filepath.Join(rootDir, \".beads_root_id\")); os.IsNotExist(err) {\n    return fmt.Errorf(\"root identity missing in %s; re-init the database\", rootDir)\n}","typeGuard":null,"tryCatchPattern":"if err := p.ListenAndServe(ctx); err != nil {\n    if strings.Contains(err.Error(), \"resolve proxy root identity\") {\n        log.Fatalf(\"rootDir identity unreadable/incompatible: %v - re-run init\", err)\n    }\n    log.Fatal(err)\n}","preventionTips":["Copy database directories with all hidden identity files (cp -a, tar)","Run init after restoring from backup to regenerate metadata","Keep proxy and CLI tool versions in lockstep to avoid schema drift"],"tags":["identity","metadata","schema","rootdir"],"backgroundTag":"missing-root-identity","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}