diff --git a/lua/avante/file_selector.lua b/lua/avante/file_selector.lua
index aa6e280..4af6ac6 100644
--- a/lua/avante/file_selector.lua
+++ b/lua/avante/file_selector.lua
@@ -363,26 +363,14 @@ end
 function FileSelector:get_selected_files_contents()
   local contents = {}
   for _, file_path in ipairs(self.selected_filepaths) do
-    --- Lookup if the file is loaded in a buffer
-    local bufnr = vim.fn.bufnr(file_path)
-    if bufnr ~= -1 and vim.api.nvim_buf_is_loaded(bufnr) then
-      -- If buffer exists and is loaded, get buffer content
-      local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
-      local content = table.concat(lines, "\n")
-      local filetype = vim.api.nvim_get_option_value("filetype", { buf = bufnr })
-      table.insert(contents, { path = file_path, content = content, file_type = filetype })
+    local lines, filetype, error = Utils.read_file_from_buf_or_disk(file_path)
+    lines = lines or {}
+    filetype = filetype or "unknown"
+    if error ~= nil then
+      Utils.error("error reading file: " .. error)
     else
-      -- Fallback: read file from disk
-      local file, open_err = io.open(file_path, "r")
-      if file then
-        local content = file:read("*all")
-        file:close()
-        -- Detect the file type using the specific file's content
-        local filetype = vim.filetype.match({ filename = file_path, contents = { content } }) or "unknown"
-        table.insert(contents, { path = file_path, content = content, file_type = filetype })
-      else
-        Utils.debug("error reading file:", open_err)
-      end
+      local content = table.concat(lines, "\n")
+      table.insert(contents, { path = file_path, content = content, file_type = filetype })
     end
   end
   return contents
diff --git a/lua/avante/llm_tools.lua b/lua/avante/llm_tools.lua
index e326760..9d75346 100644
--- a/lua/avante/llm_tools.lua
+++ b/lua/avante/llm_tools.lua
@@ -120,9 +120,9 @@ function M.read_file_toplevel_symbols(opts, on_log)
   local filetype = RepoMap.get_ts_lang(abs_path)
   local repo_map_lib = RepoMap._init_repo_map_lib()
   if not repo_map_lib then return "", "Failed to load avante_repo_map" end
-  local definitions = filetype
-      and repo_map_lib.stringify_definitions(filetype, Utils.file.read_content(abs_path) or "")
-    or ""
+  local lines = Utils.read_file_from_buf_or_disk(abs_path)
+  local content = lines and table.concat(lines, "\n") or ""
+  local definitions = filetype and repo_map_lib.stringify_definitions(filetype, content) or ""
   return definitions, nil
 end
 
diff --git a/lua/avante/repo_map.lua b/lua/avante/repo_map.lua
index 9cb99fd..c639922 100644
--- a/lua/avante/repo_map.lua
+++ b/lua/avante/repo_map.lua
@@ -64,9 +64,9 @@ function RepoMap._build_repo_map(project_root, file_ext)
   vim.iter(filepaths):each(function(filepath)
     if not Utils.is_same_file_ext(file_ext, filepath) then return end
     local filetype = RepoMap.get_ts_lang(filepath)
-    local definitions = filetype
-        and repo_map_lib.stringify_definitions(filetype, Utils.file.read_content(filepath) or "")
-      or ""
+    local lines = Utils.read_file_from_buf_or_disk(filepath)
+    local content = lines and table.concat(lines, "\n") or ""
+    local definitions = filetype and repo_map_lib.stringify_definitions(filetype, content) or ""
     if definitions == "" then return end
     table.insert(output, {
       path = Utils.relative_path(filepath),
@@ -127,10 +127,9 @@ function RepoMap._get_repo_map(file_ext)
   local update_repo_map = vim.schedule_wrap(function(rel_filepath)
     if rel_filepath and Utils.is_same_file_ext(file_ext, rel_filepath) then
       local abs_filepath = PPath:new(project_root):joinpath(rel_filepath):absolute()
-      local definitions = repo_map_lib.stringify_definitions(
-        RepoMap.get_ts_lang(abs_filepath),
-        Utils.file.read_content(abs_filepath) or ""
-      )
+      local lines = Utils.read_file_from_buf_or_disk(abs_filepath)
+      local content = lines and table.concat(lines, "\n") or ""
+      local definitions = repo_map_lib.stringify_definitions(RepoMap.get_ts_lang(abs_filepath), content)
       if definitions == "" then return end
       local found = false
       for _, m in ipairs(repo_map) do
diff --git a/lua/avante/sidebar.lua b/lua/avante/sidebar.lua
index 17abcba..12c3a63 100644
--- a/lua/avante/sidebar.lua
+++ b/lua/avante/sidebar.lua
@@ -255,11 +255,12 @@ local function transform_result_content(selected_files, result_content, prev_fil
           Utils.warn("Not a file: " .. filepath)
           goto continue
         end
-        local content = Utils.file.read_content(filepath)
-        if content == nil then
+        local lines = Utils.read_file_from_buf_or_disk(filepath)
+        if lines == nil then
           Utils.warn("Failed to read file: " .. filepath)
           goto continue
         end
+        local content = table.concat(lines, "\n")
         the_matched_file = {
           filepath = filepath,
           content = content,
@@ -534,11 +535,12 @@ local function ensure_snippets_no_overlap(snippets_map)
   for filepath, snippets in pairs(snippets_map) do
     table.sort(snippets, function(a, b) return a.range[1] < b.range[1] end)
 
-    local original_content = ""
+    local original_lines = {}
     local file_exists = Utils.file.exists(filepath)
-    if file_exists then original_content = Utils.file.read_content(filepath) or "" end
-
-    local original_lines = vim.split(original_content, "\n")
+    if file_exists then
+      local original_lines_ = Utils.read_file_from_buf_or_disk(filepath)
+      if original_lines_ then original_lines = original_lines_ end
+    end
 
     local new_snippets = {}
     local last_end_line = 0
@@ -584,9 +586,7 @@ local function insert_conflict_contents(bufnr, snippets)
   -- sort snippets by start_line
   table.sort(snippets, function(a, b) return a.range[1] < b.range[1] end)
 
-  local content = table.concat(Utils.get_buf_lines(0, -1, bufnr), "\n")
-
-  local lines = vim.split(content, "\n")
+  local lines = Utils.get_buf_lines(0, -1, bufnr)
 
   local offset = 0
 
@@ -714,7 +714,15 @@ end
 ---@param snippets_map table<string, AvanteCodeSnippet[]>
 ---@return table<string, AvanteCodeSnippet[]>
 function Sidebar:minimize_snippets(snippets_map)
-  local original_lines = api.nvim_buf_get_lines(self.code.bufnr, 0, -1, false)
+  local original_lines = {}
+
+  if vim.tbl_count(snippets_map) > 0 then
+    local filepaths = vim.tbl_keys(snippets_map)
+    local original_lines_, _, err = Utils.read_file_from_buf_or_disk(filepaths[1])
+    if err ~= nil then return {} end
+    if original_lines_ then original_lines = original_lines_ end
+  end
+
   local results = {}
 
   for filepath, snippets in pairs(snippets_map) do
diff --git a/lua/avante/utils/init.lua b/lua/avante/utils/init.lua
index 2dbbdcf..881cc40 100644
--- a/lua/avante/utils/init.lua
+++ b/lua/avante/utils/init.lua
@@ -890,4 +890,32 @@ function M.is_same_file(filepath_a, filepath_b) return M.uniform_path(filepath_a
 
 function M.trim_think_content(content) return content:gsub("^<think>.-</think>", "", 1) end
 
+---@param file_path string
+---@return string[]|nil lines
+---@return string|nil file_type
+---@return string|nil error
+function M.read_file_from_buf_or_disk(file_path)
+  --- Lookup if the file is loaded in a buffer
+  local bufnr = vim.fn.bufnr(file_path)
+  if bufnr ~= -1 and vim.api.nvim_buf_is_loaded(bufnr) then
+    -- If buffer exists and is loaded, get buffer content
+    local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+    local file_type = vim.api.nvim_get_option_value("filetype", { buf = bufnr })
+    return lines, file_type, nil
+  end
+
+  -- Fallback: read file from disk
+  local file, open_err = io.open(file_path, "r")
+  if file then
+    local content = file:read("*all")
+    file:close()
+    -- Detect the file type using the specific file's content
+    local file_type = vim.filetype.match({ filename = file_path, contents = { content } }) or "unknown"
+    return vim.split(content, "\n"), file_type, nil
+  else
+    M.error("failed to open file: " .. file_path .. " with error: " .. open_err)
+    return nil, nil, open_err
+  end
+end
+
 return M