{"record":{"id":"5516b5c58b8d6a4a","repo":"charmbracelet/crush","slug":"failed-to-create-gitignore-file-q-w","errorCode":null,"errorMessage":"failed to create .gitignore file: %q %w","messagePattern":"failed to create \\.gitignore file: %q %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/util.go","lineNumber":17,"sourceCode":"package backend\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\nfunc createDotCrushDir(dir string) error {\n\tif err := os.MkdirAll(dir, 0o700); err != nil {\n\t\treturn fmt.Errorf(\"failed to create data directory: %q %w\", dir, err)\n\t}\n\n\tgitIgnorePath := filepath.Join(dir, \".gitignore\")\n\tif _, err := os.Stat(gitIgnorePath); os.IsNotExist(err) {\n\t\tif err := os.WriteFile(gitIgnorePath, []byte(\"*\\n\"), 0o644); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create .gitignore file: %q %w\", gitIgnorePath, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/backend/util.go#L1-L23","documentation":"After creating the data directory, createDotCrushDir writes a .gitignore containing \"*\\n\" (mode 0644) so workspace data is never committed. This error wraps os.WriteFile failure for that file, meaning the directory exists but the ignore file could not be created.","triggerScenarios":"CreateWorkspace -> createDotCrushDir where the directory was created (or already existed) but os.WriteFile(gitIgnorePath, ...) fails — permission denied on the directory, .gitignore exists as a directory, disk full, or the directory was made read-only between creation and write.","commonSituations":"Antivirus or security software locking new files; a directory literally named .gitignore inside the data dir; quota exhaustion on network filesystems (NFS homes).","solutions":["Check whether the quoted .gitignore path collides with an existing directory and remove/rename it.","Verify write permission on the data directory itself (chmod u+w).","Check disk quota/remaining space.","Re-run CreateWorkspace; the .gitignore creation is idempotent (skipped when it already exists)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"p := filepath.Join(dir, \".gitignore\")\nif fi, err := os.Stat(p); err == nil && fi.IsDir() {\n    return fmt.Errorf(\"%s is a directory, cannot write .gitignore\", p)\n}","typeGuard":"func IsGitignoreWriteErr(err error) (string, bool) {\n    var pe *fs.PathError\n    if errors.As(err, &pe) {\n        return pe.Path, true\n    }\n    return \"\", false\n}","tryCatchPattern":"if err := createDotCrushDir(dir); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {\n        os.Chmod(dir, 0o700) // restore write access, then retry once\n        return createDotCrushDir(dir)\n    }\n    return err\n}","preventionTips":["Never create a file or directory named .gitignore inside the data dir.","Check directory write permission right after MkdirAll.","Watch for security software that locks newly created files.","On network filesystems, verify quota before large workspace creation."],"tags":["filesystem","gitignore","permissions","go"],"backgroundTag":"file-write-permission-denied","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}