{"record":{"id":"f8c9165c985cd8cf","repo":"charmbracelet/crush","slug":"failed-to-initialize-config-w","errorCode":null,"errorMessage":"failed to initialize config: %w","messagePattern":"failed to initialize config: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/backend.go","lineNumber":416,"sourceCode":"\t\tb.pending--\n\t\t// If this create ended up registering nothing (it failed, or\n\t\t// deduped onto an existing workspace that has since gone) and\n\t\t// it was holding the last teardown back, the server may now be\n\t\t// idle with no pending work. Arm the idle-shutdown timer here so\n\t\t// a failed create racing the last teardown does not leak an\n\t\t// empty server that a plain teardown already declined to reap.\n\t\tshutdownNow := b.scheduleShutdownIfIdleLocked()\n\t\tb.mu.Unlock()\n\t\tif shutdownNow {\n\t\t\tslog.Info(\"No workspaces remain after create settled, shutting down server...\")\n\t\t\tb.shutdownFn()\n\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.","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/backend/backend.go#L398-L434","documentation":"After resolving the workspace key, CreateWorkspace initializes the config service via config.Init(path, dataDir, debug). Any error loading/validating crushrc or crush.json for that workspace is wrapped with this message.","triggerScenarios":"config.Init fails because the workspace's crushrc/crush.json has a syntax error, fails schema validation, or cannot be read (permissions), or the data directory is unusable.","commonSituations":"Malformed crushrc bash syntax; invalid JSON in crush.json; unsupported/unknown keys after version upgrades; unreadable config file permissions.","solutions":["Run 'crush' interactively or validate the config to see the underlying wrapped error and fix it","Fix syntax errors in crushrc / crush.json (deprecated but still parsed)","Check file permissions on the config file and data directory"],"exampleFix":"// before (crushrc)\nprovider anthropic\n  model claude\n  # unclosed block\n// after\nprovider \"anthropic\"\n  model \"anthropic/claude-sonnet-4\"\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"ws, err := b.CreateWorkspace(ctx, args)\nif err != nil {\n    var cfgErr = \"failed to initialize config\"\n    if strings.Contains(err.Error(), cfgErr) {\n        // surface underlying %w cause to user, e.g. run config validation\n        return fmt.Errorf(\"workspace config invalid: %w\", err)\n    }\n    return err\n}","preventionTips":["Validate crushrc/crush.json syntax before shipping config changes","Keep config files readable by the user running crush","Test config changes interactively before using non-interactive mode"],"tags":["config","workspace","initialization"],"backgroundTag":"config-init-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}