{"record":{"id":"66ff816508506c4e","repo":"gastownhall/beads","slug":"workspacegate-resolving-s-w","errorCode":null,"errorMessage":"workspacegate: resolving %s: %w","messagePattern":"workspacegate: resolving (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/workspacegate/gate.go","lineNumber":165,"sourceCode":"\n// gateFileName maps a guarded directory base name to its sibling gate\n// file name: \".beads\" -> \".beads.gate.lock\", \"dolt\" -> \"dolt.gate.lock\".\n// The base is kept verbatim (no dot-stripping) so distinct sibling names\n// can never collide on one gate file.\nfunc gateFileName(base string) string {\n\treturn base + \".gate.lock\"\n}\n\n// forDir builds the gate for a guarded directory: the gate file sits in\n// the directory's parent. The parent must exist; the guarded directory\n// itself may not exist yet (bd init gates the workspace it is creating).\n// The parent is canonicalized (symlinks resolved) so that every process\n// that reaches the same physical parent agrees on one gate file, no\n// matter which path spelling it used.\nfunc forDir(dir string) (Gate, error) {\n\tabs, err := filepath.Abs(dir)\n\tif err != nil {\n\t\treturn Gate{}, fmt.Errorf(\"workspacegate: resolving %s: %w\", dir, err)\n\t}\n\tabs = filepath.Clean(abs)\n\n\t// Gate identity must be stable across the guarded directory being\n\t// absent, created, replaced, or recreated — that is the point of\n\t// placing the gate beside it. So identity derives from the\n\t// canonicalized PARENT plus the literal base name, never from\n\t// resolving the guarded path itself: full-path resolution would\n\t// silently select a different gate once the directory appears as a\n\t// symlink, letting two exclusive holders coexist. The flip side is\n\t// that a guarded directory that IS a symlink has no stable identity\n\t// under this scheme, so it is refused outright rather than gated\n\t// ambiguously.\n\tif fi, err := os.Lstat(abs); err == nil && fi.Mode()&os.ModeSymlink != 0 {\n\t\treturn Gate{}, fmt.Errorf(\"workspacegate: %s is a symlink; gate the physical directory it points to\", abs)\n\t}\n\tparent, base := filepath.Split(abs)\n\tswitch base {","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/workspacegate/gate.go#L147-L183","documentation":"workspacegate.forDir fails to resolve the given directory to an absolute path, wrapping the underlying filepath.Abs error as \"workspacegate: resolving %s: %w\". This happens before the gate file identity is computed, so no lock was taken. It is an infrastructure-level resolution failure, not a gate-conflict error.","triggerScenarios":"Calling ForWorkspace(dir) or ForPhysicalRoot(dir) with a path that cannot be made absolute — practically this occurs when the current working directory is unavailable (e.g. the directory was deleted) and dir is relative, or on OS-level path resolution failures.","commonSituations":"Running bd from a directory that was removed or renamed by another process; containers or shells with a deleted cwd; extremely long or invalid path components on some filesystems.","solutions":["Re-run the command from an existing directory (cd to a valid path first)","Pass an absolute path to ForWorkspace/ForPhysicalRoot so filepath.Abs does not need the cwd","Inspect the wrapped error (%w) for the OS-specific cause (e.g. ENOENT, ENAMETOOLONG) and fix the path accordingly"],"exampleFix":"// before\ng, err := workspacegate.ForWorkspace(relDir)\n// after\nabs, err := filepath.Abs(relDir)\nif err != nil { return fmt.Errorf(\"bad workdir %q: %w\", relDir, err) }\ng, err := workspacegate.ForWorkspace(abs)","handlingStrategy":"try-catch","validationCode":"if abs, err := filepath.Abs(dir); err != nil { return fmt.Errorf(\"cannot resolve %q: %w\", dir, err) }","typeGuard":null,"tryCatchPattern":"g, err := workspacegate.ForWorkspace(dir)\nif err != nil && strings.HasPrefix(err.Error(), \"workspacegate: resolving \") { /* cwd/path issue: cd to a valid dir or use absolute path */ }","preventionTips":["Pass absolute, existing directories to gate entry points","Check that the process cwd exists before relative-path calls (containers often have deleted cwds)","Surface the wrapped %w error to diagnose OS-level causes like ENOENT or ENAMETOOLONG"],"tags":["filesystem","path","workspacegate"],"backgroundTag":"path-resolution-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}