{"record":{"id":"7588c0749c2c9188","repo":"charmbracelet/crush","slug":"failed-to-connect-to-database-w","errorCode":null,"errorMessage":"failed to connect to database: %w","messagePattern":"failed to connect to database: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/backend.go","lineNumber":428,"sourceCode":"\t\t}\n\t}()\n\n\tid := uuid.New().String()\n\tcfg, err := config.Init(args.Path, args.DataDir, args.Debug)\n\tif err != nil {\n\t\treturn nil, proto.Workspace{}, fmt.Errorf(\"failed to initialize config: %w\", err)\n\t}\n\n\tcfg.Overrides().SkipPermissionRequests = args.YOLO\n\tcfg.Overrides().EnabledChannels = args.Channels\n\n\tif err := createDotCrushDir(cfg.Config().Options.DataDirectory); err != nil {\n\t\treturn nil, proto.Workspace{}, fmt.Errorf(\"failed to create data directory: %w\", err)\n\t}\n\n\tconn, err := db.Connect(b.ctx, cfg.Config().Options.DataDirectory, db.WithDataDirLock(true))\n\tif err != nil {\n\t\treturn nil, proto.Workspace{}, fmt.Errorf(\"failed to connect to database: %w\", err)\n\t}\n\n\t// Discover skills once per workspace, before app.New. The backend\n\t// hosts multiple workspaces concurrently, so the manager is\n\t// constructed WITHOUT WithGlobalMirror to prevent last-writer-wins\n\t// cross-talk between workspaces.\n\tdiscoveryCfg := skillsDiscoveryConfig(cfg)\n\tallSkills, activeSkills, skillStates := skills.DiscoverFromConfig(discoveryCfg)\n\tskillsMgr := skills.NewManager(\n\t\tallSkills, activeSkills, skillStates,\n\t\tskills.WithResolvedPaths(discoveryCfg.ResolvePaths()),\n\t\tskills.WithWorkingDir(discoveryCfg.WorkingDir),\n\t)\n\n\tappWorkspace, err := app.New(b.ctx, conn, cfg, skillsMgr)\n\tif err != nil {\n\t\treturn nil, proto.Workspace{}, fmt.Errorf(\"failed to create app workspace: %w\", err)\n\t}","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/backend/backend.go#L410-L446","documentation":"After the data directory exists, CreateWorkspace opens the workspace SQLite database via db.Connect with a data-dir lock. Any connection failure (locked by another process, unreadable/corrupt DB file, unable to create the DB) is wrapped with this message.","triggerScenarios":"db.Connect fails: another crush instance holds the data-dir lock, the SQLite file is corrupt or unreadable, or the filesystem cannot create/write the database file.","commonSituations":"Two crush sessions sharing one data directory concurrently; stale lock after a crash; corrupt crush.db after disk issue; NFS/network filesystem that breaks SQLite locking.","solutions":["Close other crush instances using the same data directory","Remove a stale lock file / move the corrupt DB aside to re-initialize","Move the data directory onto a local (non-NFS) filesystem"],"exampleFix":"// before\ncrush run  # database is locked\n// after\npkill crush\nrm ~/.crush/*.lock\ncrush run","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"ws, err := b.CreateWorkspace(ctx, args)\nif err != nil && strings.Contains(err.Error(), \"failed to connect to database\") {\n    time.Sleep(500 * time.Millisecond)\n    ws, err = b.CreateWorkspace(ctx, args) // retry once; another instance may hold the lock\n}\nif err != nil {\n    return err\n}","preventionTips":["Use one data directory per running crush instance","Store the DB on a local filesystem, not NFS","After a crash, clear stale locks before restarting"],"tags":["database","sqlite","locking"],"backgroundTag":"database-locked","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}