fix: preserve source dolt_database across .beads/redirect#2605
Open
mrmaxsteel wants to merge 1 commit intosteveyegge:mainfrom
Open
fix: preserve source dolt_database across .beads/redirect#2605mrmaxsteel wants to merge 1 commit intosteveyegge:mainfrom
mrmaxsteel wants to merge 1 commit intosteveyegge:mainfrom
Conversation
When bd follows a .beads/redirect file (e.g., from a rig to the Gas Town root), it loads metadata.json from the TARGET directory. This overwrites the source rig's dolt_database with the target's (e.g., "hq" instead of "lola"), causing bd list/show to query the wrong database. This affects both: 1. CWD path: running bd from a rig directory 2. Routing path: gt sling/bd show <routed-id> from the town root Fix: - Add ResolveRedirect() that reads source metadata.json (raw JSON, no Dolt connection) before following the redirect - In main.go: set BEADS_DOLT_SERVER_DATABASE early so all store opens use the correct database - In routing/routes.go: ResolveBeadsDirForID and ResolveBeadsDirForRig use ResolveRedirect and set the env var when a redirect changes the DB - In routed.go: treat env var override as "routes differently" even when the target directory is the same (centralized Dolt serves multiple DBs from one .beads dir) The env var BEADS_DOLT_SERVER_DATABASE retains highest priority — the fix only sets it when not already set. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a0deccb to
869b5cc
Compare
Contributor
DreadPirateRobertz
left a comment
There was a problem hiding this comment.
Thorough analysis of the redirect path losing dolt_database. The fix approach — preserving source metadata across redirect follows — is correct.
One question: does this introduce any risk for the common worktree case where source and target should share the same dolt_database? If the source's metadata is stale (e.g., someone renamed the database in the target but forgot the source), preserving the stale source value could cause issues.
The detailed git archaeology tracing when this bug surfaced is very helpful for reviewers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When
bdfollows a.beads/redirectfile, it loadsmetadata.jsonfrom the target directory, silently discarding the source directory'sdolt_databasefield. If the source and target have differentdolt_databasevalues (e.g., source says"lola", target says"hq"), all subsequent queries hit the wrong database.This is a contract violation in the redirect feature: the source's
metadata.jsonexplicitly declares its database identity, but following a redirect overwrites it with the target's identity.Why this is a beads bug (not a consumer bug)
The redirect was originally designed for worktrees where source and target share the same
dolt_database. But the redirect mechanism doesn't document or enforce that constraint. When a consumer legitimately sets up a redirect between directories with different databases (e.g., a multi-database Dolt server), the source'sdolt_databaseis silently lost. This affects:bd listfrom a directory with a redirect shows the wrong database's issuesbd show <prefixed-id>from a parent directory routes throughroutes.jsonl, follows the redirect, and queries the wrong databaseAny multi-database redirect setup would hit this — the fix belongs in beads' redirect handling, not in consumers.
Why this bug wasn't hit until now
The bug has existed since
FollowRedirectwas written — it never preserved the source'sdolt_database. However, consumers didn't trigger it until recently because the redirect was only used between directories with the samedolt_database(worktrees sharing a parent repo's database).Gas Town began creating redirects between directories with different
dolt_databasevalues in Jan 2026 (steveyegge/gastown@9d7dcde1). Even then, the bug was accidentally avoided because Gas Town calledbdfrom the rig directory, wherebdloaded the correct local metadata before following the redirect.The bug became visible on Mar 12 2026 when steveyegge/gastown@1a1f3f7b changed to calling
bdfrom the parent directory instead (to fix a nested routing issue). This meantbdhit the routing path — prefix match → follow redirect → load target metadata → wrong database.Downstream impact
This bug affects any consumer using redirects with a centralized multi-database Dolt server. The specific failure mode:
.beads/metadata.json(dolt_database: "projA") and a redirect to shared directory B (dolt_database: "default")bd listfrom A shows B's issues instead of A'sbd show projA-xxxfrom B (via prefix routing) follows the redirect back to B, queries "default" database → "not found"In Gas Town (the primary consumer), this manifests as:
gt sling <bead> <rig>fails with "bead not found" — the bead exists in the rig's database butbdqueries the wrong one (bd init creates databases with inconsistent naming — prefix vs rig name causes split-brain gastown#2682 describes a related split-brain scenario)bd listfrom a rig directory shows another database's issuesFix
internal/beads/beads.go: AddResolveRedirect()that reads the source'smetadata.json(raw JSON, no Dolt connection) to capturedolt_databasebefore following the redirectcmd/bd/main.go: SetBEADS_DOLT_SERVER_DATABASEearly in startup when a redirect changes the database, so all store opens use the correct databaseinternal/routing/routes.go:ResolveBeadsDirForIDandResolveBeadsDirForRiguseResolveRedirectand set the env var when a redirect changes the DBcmd/bd/routed.go: Treat env var override as "routes differently" even when the target directory is the same (shared Dolt server serves multiple DBs from one.beadsdir)The env var
BEADS_DOLT_SERVER_DATABASEretains highest priority — the fix only sets it when not already set.Test plan
make buildsucceedsbd listfrom a redirected directory shows the correct database's issuesbd show <prefixed-id>from a parent directory (routing path) finds the correct issueBEADS_DOLT_SERVER_DATABASEenv var is not overriddengt slingsuccessfully dispatches work after fix🤖 Generated with Claude Code