{"record":{"id":"762f6949cf097837","repo":"gastownhall/beads","slug":"uow-team-server-identity-check-on-database-q-w","errorCode":null,"errorMessage":"uow: team-server identity check on database %q: %w","messagePattern":"uow: team-server identity check on database %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/team_server_schema.go","lineNumber":68,"sourceCode":"//\n// expectedProjectID is empty for the paths that legitimately have no\n// assertion to make (`bd init`, which adopts, and server-wide database\n// maintenance); those skip the check.\nfunc checkTeamServerIdentity(ctx context.Context, conn schema.DBConn, database, expectedProjectID string) error {\n\t// Soft-skip semantics deliberately mirror DoltStore.verifyProjectIdentity:\n\t// an empty id on EITHER side means \"no assertion available\", not\n\t// \"mismatch\", so workspaces and databases that predate project identity\n\t// keep working.\n\tif expectedProjectID == \"\" {\n\t\treturn nil\n\t}\n\t// A read error is surfaced rather than skipped: checkTeamServerSchema has\n\t// already proven the beads schema is present at this binary's version, so\n\t// the metadata table exists and a failure here is a real fault, not the\n\t// legacy-database case verifyProjectIdentity tolerates.\n\tdbProjectID, err := issueops.GetMetadataInTx(ctx, conn, \"_project_id\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"uow: team-server identity check on database %q: %w\", database, err)\n\t}\n\t// Unlike verifyProjectIdentity, an absent stored identity is NOT tolerated\n\t// here. adoptTeamServerIdentity refuses to attach to a bts database that\n\t// has no metadata._project_id at all, so for a team-server database this\n\t// is an already-invalid state rather than a legacy one — and soft-skipping\n\t// it would mean deleting one row from the shared database silently\n\t// disables this guard for every client.\n\tif dbProjectID == \"\" {\n\t\treturn fmt.Errorf(\n\t\t\t\"uow: database %q has no project identity (metadata._project_id) — the schema is managed by beads-team-server; ask your operator to provision it with 'bts init' (or heal an older bts database with 'bts migrate')\",\n\t\t\tdatabase)\n\t}\n\tif dbProjectID != expectedProjectID {\n\t\treturn fmt.Errorf(\n\t\t\t\"PROJECT IDENTITY MISMATCH — refusing to connect\\n\\n\"+\n\t\t\t\t\"  Local project ID (metadata.json):  %s\\n\"+\n\t\t\t\t\"  Database %q project ID:            %s\\n\\n\"+\n\t\t\t\t\"The team server is serving a DIFFERENT project's database.\\n\"+","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/team_server_schema.go#L50-L86","documentation":"checkTeamServerIdentity reads the database's stored project identity (metadata._project_id) via GetMetadataInTx and wraps any read failure. At this point the schema check has already proven the metadata table exists, so an error here indicates a real fault querying the shared database, not a legacy-schema situation.","triggerScenarios":"GetMetadataInTx(ctx, conn, \"_project_id\") returns an error during verifyTeamServerSchema — e.g. SQL error, connection drop mid-query, permission denial on the metadata table, or ctx cancellation.","commonSituations":"Transient network failure to the Dolt server during connect; revoked/insufficient SQL grants on the metadata table; server-side error while reading metadata; ctx timeout expiring mid-query.","solutions":["Retry the command — transient connection/query failures are the most common cause","Check SQL grants: the bd user must be able to read the metadata table","Verify server health/logs if the error persists","Ensure network stability to the dolt server (timeouts, TLS, proxy)","Check ctx timeouts are not too aggressive for the server round-trip"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"// Go: verify read access to metadata before the identity check\nvar v string\nerr := conn.QueryContext(ctx, \"SELECT value FROM metadata WHERE `key` = '_project_id'\")","typeGuard":"func isIdentityReadError(err error) bool {\n  return err != nil && strings.Contains(err.Error(), \"team-server identity check on database\")\n}","tryCatchPattern":"err := bdSync(ctx)\nvar netErr net.Error\nif isIdentityReadError(err) && (errors.As(err, &netErr) || errors.Is(err, context.DeadlineExceeded)) {\n  // transient: retry with backoff\n  time.Sleep(2 * time.Second); err = bdSync(ctx)\n}\nreturn err","preventionTips":["Ensure the bd SQL user has SELECT grants on the metadata table","Use stable network paths to the Dolt server (avoid flaky proxies)","Set realistic query timeouts for remote servers","Retry transient wrapped errors; escalate persistent ones to server logs"],"tags":["database","identity","query-error","team-server"],"backgroundTag":"metadata-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}