charmbracelet/crush · error

failed to create data directory: %w

Error message

failed to create data directory: %w

What it means

CreateWorkspace calls createDotCrushDir on the configured data directory to ensure the .crush storage location exists. Failure to create it (permissions, read-only FS, path is a file) is wrapped with this message.

Source

Thrown at internal/backend/backend.go:423

		shutdownNow := b.scheduleShutdownIfIdleLocked()
		b.mu.Unlock()
		if shutdownNow {
			slog.Info("No workspaces remain after create settled, shutting down server...")
			b.shutdownFn()
		}
	}()

	id := uuid.New().String()
	cfg, err := config.Init(args.Path, args.DataDir, args.Debug)
	if err != nil {
		return nil, proto.Workspace{}, fmt.Errorf("failed to initialize config: %w", err)
	}

	cfg.Overrides().SkipPermissionRequests = args.YOLO
	cfg.Overrides().EnabledChannels = args.Channels

	if err := createDotCrushDir(cfg.Config().Options.DataDirectory); err != nil {
		return nil, proto.Workspace{}, fmt.Errorf("failed to create data directory: %w", err)
	}

	conn, err := db.Connect(b.ctx, cfg.Config().Options.DataDirectory, db.WithDataDirLock(true))
	if err != nil {
		return nil, proto.Workspace{}, fmt.Errorf("failed to connect to database: %w", err)
	}

	// Discover skills once per workspace, before app.New. The backend
	// hosts multiple workspaces concurrently, so the manager is
	// constructed WITHOUT WithGlobalMirror to prevent last-writer-wins
	// cross-talk between workspaces.
	discoveryCfg := skillsDiscoveryConfig(cfg)
	allSkills, activeSkills, skillStates := skills.DiscoverFromConfig(discoveryCfg)
	skillsMgr := skills.NewManager(
		allSkills, activeSkills, skillStates,
		skills.WithResolvedPaths(discoveryCfg.ResolvePaths()),
		skills.WithWorkingDir(discoveryCfg.WorkingDir),
	)

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check/fix permissions on the data directory's parent and recreate with mkdir
  2. Point the data directory override at a writable location
  3. Remove any regular file occupying the data-directory path

Example fix

// before
crush run  # ~/.crush owned by root
// after
sudo chown -R $USER ~/.crush
# or set a writable data dir
crush run --data-dir /tmp/crush-data
Defensive patterns

Strategy: validation

Validate before calling

dataDir := cfg.Config().Options.DataDirectory
if fi, err := os.Stat(dataDir); err == nil && !fi.IsDir() {
    return fmt.Errorf("data dir %s exists and is not a directory", dataDir)
}
if err := os.MkdirAll(dataDir, 0o755); err != nil {
    return fmt.Errorf("cannot create data dir: %w", err)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to create data directory") {
    return fmt.Errorf("check permissions/writability of data dir: %w", err)
}

Prevention

When it happens

Trigger: cfg.Config().Options.DataDirectory cannot be MkdirAll'd — parent dir not writable, path exists as a regular file, disk full, or read-only mount.

Common situations: Running in a sandbox/container with read-only home; DATA_DIR pointing at a file; running as a different user than the directory owner.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/c818e4771bd79f33. Report an issue: GitHub.