JuliusBrussee/caveman · error
repository intelligence: cwd is not a directory
Error message
repository intelligence: cwd is not a directory
What it means
repointel.Build resolves the root path through symlink evaluation and absolutization, then stats it. If stat fails or the result is not a directory, it reports that the cwd/repository root is not a directory. Note the error also masks the underlying stat error, so permission problems surface the same way.
Source
Thrown at proxy/internal/repointel/index.go:104
ChangedPaths []string `json:"changed_paths"`
AffectedTests []string `json:"affected_tests"`
Basis string `json:"basis"`
EvidenceStatus string `json:"evidence_status"`
Conservative bool `json:"conservative"`
}
func Build(ctx context.Context, root, repositoryState string, queryTerms []string) (Map, Bundle, error) {
resolved, err := filepath.EvalSymlinks(root)
if err != nil {
return Map{}, Bundle{}, err
}
resolved, err = filepath.Abs(resolved)
if err != nil {
return Map{}, Bundle{}, err
}
info, err := os.Stat(resolved)
if err != nil || !info.IsDir() {
return Map{}, Bundle{}, errors.New("repository intelligence: cwd is not a directory")
}
files, truncated, err := listFiles(ctx, resolved)
if err != nil {
return Map{}, Bundle{}, err
}
packages := packageBoundaries(files)
activity := gitActivity(ctx, resolved)
mapped := make([]File, 0, len(files))
for _, relative := range files {
entry := File{
Path: relative, Language: languageFor(relative), Package: nearestPackage(relative, packages),
TestFor: testTarget(relative, files), RecentChanges: activity[relative], Convention: isConvention(relative),
}
if entry.Language != "" && !sensitivePath(relative) {
path := filepath.Join(resolved, filepath.FromSlash(relative))
if raw, readErr := os.ReadFile(path); readErr == nil && len(raw) <= maxFileBytes && !containsNUL(raw) {
entry.Imports = scanImports(entry.Language, raw)
entry.Symbols = scanSymbols(ctx, relative, entry.Language, raw)View on GitHub (pinned to 27d5a3981a)
Solutions
- Pass the repository root directory, not any file inside it
- Verify the path exists and is a directory before calling Build (os.Stat + IsDir)
- If permissions are suspect, check the resolved path's modes and the mount state
Example fix
// before
map, bundle, err := repointel.Build(ctx, "repo/go.mod", state, terms)
// after
info, err := os.Stat(root)
if err != nil || !info.IsDir() {
return fmt.Errorf("root %q is not a directory", root)
}
map, bundle, err := repointel.Build(ctx, root, state, terms) Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(root)
if err != nil || !info.IsDir() {
return fmt.Errorf("root %q is not a directory", root)
}
mp, bundle, err := repointel.Build(ctx, root, state, terms) Type guard
func isDir(p string) bool {
info, err := os.Stat(p)
return err == nil && info.IsDir()
} Prevention
- Pass repository roots, never files, to Build
- Resolve symlinks yourself first to see what the path really points at
When it happens
Trigger: Calling Build with a path that is a file (e.g. go.mod, a symlink to a file), a deleted directory, or a directory the process cannot stat due to permissions.
Common situations: Passing the repo's manifest file instead of its root; root resolved from config pointing at a mounted/unmounted volume; symlink chains that EvalSymlinks resolves to a file; sandboxed environments denying stat.
Related errors
- File not found: {filepath}
- File too large to compress safely (max 500KB): {filepath}
- cachebench: nil corpus reader
- message exceeds byte limit
- tool message requires tool_call_id
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/4b70225b7b7898fa.
Report an issue: GitHub.