charmbracelet/crush · error

failed to create file: %w

Error message

failed to create file: %w

What it means

When applying a CreateFile document change, applyDocumentChange creates an empty file with os.WriteFile. This error wraps any failure (permission denied, parent directory missing, filesystem read-only). Options like Overwrite/IgnoreIfExists are handled before this call, so this is a hard create failure.

Source

Thrown at internal/lsp/util/edit.go:188

// applyDocumentChange applies a DocumentChange (create/rename/delete operations)
func applyDocumentChange(change protocol.DocumentChange, encoding powernap.OffsetEncoding) error {
	if change.CreateFile != nil {
		path, err := change.CreateFile.URI.Path()
		if err != nil {
			return fmt.Errorf("invalid URI: %w", err)
		}

		if change.CreateFile.Options != nil {
			if change.CreateFile.Options.Overwrite {
				// Proceed with overwrite
			} else if change.CreateFile.Options.IgnoreIfExists {
				if _, err := os.Stat(path); err == nil {
					return nil // File exists and we're ignoring it
				}
			}
		}
		if err := os.WriteFile(path, []byte(""), 0o644); err != nil {
			return fmt.Errorf("failed to create file: %w", err)
		}
	}

	if change.DeleteFile != nil {
		path, err := change.DeleteFile.URI.Path()
		if err != nil {
			return fmt.Errorf("invalid URI: %w", err)
		}

		if change.DeleteFile.Options != nil && change.DeleteFile.Options.Recursive {
			if err := os.RemoveAll(path); err != nil {
				return fmt.Errorf("failed to delete directory recursively: %w", err)
			}
		} else {
			if err := os.Remove(path); err != nil {
				return fmt.Errorf("failed to delete file: %w", err)
			}
		}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Create the parent directory (os.MkdirAll) before applying the change.
  2. Check write permission on the target directory.
  3. Ensure the filesystem/mount is writable.
  4. If the file already exists and should not be replaced, set IgnoreIfExists in CreateFileOptions.

Example fix

// before
// parent dir missing
change.CreateFile = &protocol.CreateFile{URI: newURI}
// after
os.MkdirAll(filepath.Dir(path), 0o755)
change.CreateFile = &protocol.CreateFile{URI: newURI}
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(path)
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
    os.MkdirAll(dir, 0o755)
}

Try / catch

var mkErr *fs.PathError
if errors.As(err, &mkErr) && errors.Is(mkErr.Err, fs.ErrNotExist) {
    os.MkdirAll(filepath.Dir(mkErr.Path), 0o755) // then retry create
}

Prevention

When it happens

Trigger: CreateFile change where the target directory does not exist, the process lacks write permission, or the filesystem is read-only and Overwrite/IgnoreIfExists do not bypass the write.

Common situations: Creating a file in a directory that was deleted concurrently; new-file refactors targeting a package folder not yet created; sandboxed environments without write access.

Related errors


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