gastownhall/beads · error
identity: resolve root path: %w
Error message
identity: resolve root path: %w
What it means
RootID resolves the workspace root directory to a stable ID by taking its absolute path, resolving symlinks with filepath.EvalSymlinks, and hashing the result with SHA-256. This error wraps any failure from EvalSymlinks, which fails if any component of the path does not exist or is an unreadable/broken symlink. The library throws it because it cannot compute a canonical path for a root that the filesystem does not resolve.
Source
Thrown at internal/storage/dbproxy/identity/identity.go:34
// SecretFileName is the per-workspace secret used to authenticate control
// listener requests.
const SecretFileName = "proxy.secret"
// RootID returns the SHA-256 of rootDir's symlink-resolved absolute path.
// It identifies the workspace proxy root, not the Dolt data directory;
// upstream_id continues to identify the backend through DoltServer.ID.
// Darwin's default case-insensitive filesystems can resolve the same directory
// through differently cased path spellings; callers should use a canonical
// workspace spelling when they need stable IDs across invocations.
func RootID(rootDir string) (string, error) {
abs, err := filepath.Abs(rootDir)
if err != nil {
return "", fmt.Errorf("identity: absolute root path: %w", err)
}
resolved, err := filepath.EvalSymlinks(abs)
if err != nil {
return "", fmt.Errorf("identity: resolve root path: %w", err)
}
sum := sha256.Sum256([]byte(resolved))
return hex.EncodeToString(sum[:]), nil
}
// WriteSecret creates and atomically writes a new control-listener secret.
// Each proxy start intentionally rotates the previous secret.
func WriteSecret(rootDir string) (string, error) {
raw := make([]byte, 32)
if _, err := rand.Read(raw); err != nil {
return "", fmt.Errorf("identity: generate proxy secret: %w", err)
}
secret := hex.EncodeToString(raw)
if err := atomicfile.WriteFile(filepath.Join(rootDir, SecretFileName), []byte(secret+"\n"), 0o600); err != nil {
return "", fmt.Errorf("identity: write proxy secret: %w", err)
}
return secret, nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Create the root directory before calling RootID, e.g. os.MkdirAll(rootDir, 0o755)
- Verify the path exists and is traversable: os.Stat(filepath.EvalSymlinks'd absolute path) and check errors.Is(err, fs.ErrNotExist)
- Fix or remove broken symlinks in the path chain
- Correct the rootDir value (typo, stale env var) to the actual workspace root
Example fix
// before
id, err := identity.RootID(rootDir) // fails if rootDir missing
// after
if err := os.MkdirAll(rootDir, 0o755); err != nil {
return err
}
id, err := identity.RootID(rootDir) Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(rootDir); err != nil {
return fmt.Errorf("workspace root %q unavailable: %w", rootDir, err)
}
if _, err := filepath.EvalSymlinks(rootDir); err != nil {
return fmt.Errorf("cannot resolve %q: %w", rootDir, err)
} Try / catch
id, err := identity.RootID(rootDir)
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr.Err, fs.ErrNotExist) {
// create rootDir or surface a clear setup error
}
return err
} Prevention
- Create the workspace root with os.MkdirAll before any dbproxy identity calls
- Validate the rootDir flag/env value at startup
- Watch for broken symlinks when workspaces are moved between machines
- Run the proxy as a user with traverse permission on all path components
When it happens
Trigger: Calling identity.RootID(rootDir) when rootDir does not exist on disk, when a parent directory in the path is missing, when a symlink in the path is broken (dangling), or when the process lacks permission to traverse a path component (returns *fs.PathError, often os.ErrNotExist or os.ErrPermission).
Common situations: Starting the dbproxy against a workspace directory that was never created (typo in BEADS_DIR or --root flag), running after the workspace was deleted or moved, pointing at a symlink whose target was removed, or containers with a partially mounted volume.
Related errors
- server: NewDoltServer: failed to determine absolute path of
- server: NewDoltServer: failed to determine absolute path of
- server: NewDoltServer: failed to determine absolute path of
- server: NewDoltServer: failed to determine absolute path of
- invalid workspace path: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e09e086504be3f7b.
Report an issue: GitHub.