Bug: Empty JSON chat history files cause JSONDecodeError (very rare)
Describe the bug
When using text-generation-webui with a remote llama.cpp server (http://192.168.1.24:12546/), 0-byte JSON files are created in user_data/logs/chat/<character>/ and user_data/logs/instruct/. Attempting to list chat histories or load a session throws:
json.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Summary of Code Changes (How to fixed it) Here are the three fixes applied to G:\textgen-main\modules\chat.py to handle empty/0-byte JSON chat history files:
- find_all_histories_with_first_prompts (lines 1903-1904) Purpose: Skip empty JSON files when listing chat histories for the UI sidebar.
if not file_content:
continue
Added after reading file content, before searching. Prevents empty files from appearing in history list.
- load_history (lines 2043-2045) Purpose: Gracefully handle empty JSON files when loading a specific chat session.
with open(p, 'rb') as fh:
content = fh.read()
if not content:
return {'internal': [], 'visible': [], 'metadata': {}}
f = json.loads(content)
Returns empty history structure instead of raising json.JSONDecodeError on 0-byte files.
- load_history_json (lines 2071-2072) Purpose: Handle empty file uploads/imports in the chat history import feature.
if not file.strip():
return history
Returns original history unchanged if uploaded file is empty/whitespace.
Is there an existing issue for this?
- I have searched the existing issues
Reproduction
None
Specific Circumstances
This issue occurs specifically when:
- Using a llama.cpp server via the
--llama-cpp-serverflag or API endpoint configuration (?) ,or loading/create a new char/chat on a remote device. - Starting a new chat session with a character - the server creates a placeholder JSON file before the first.message exchange
- Network interruption or timeout during the first model response - leaves a 0-byte file that never gets written to.
- Switching characters/models mid-session - triggers new history file creation that may remain empty if the switch fails.
- High latency connections to the llama.cpp server (>5s response time) where the UI creates the history file but the request times out before content is written.
The issue does not occur with:
- Local model loading (transformers, GGUF via llama.cpp Python bindings, ExLlamaV2, etc.)
- Completed chat sessions that have at least one message exchange
- Fresh installations with no prior chat history
Fix Applied
Three defensive checks added to modules/chat.py:
find_all_histories_with_first_prompts(line 1903-1904): Skip empty files when building history listload_history(lines 2043-2045): Return empty history struct instead of crashing on empty fileload_history_json(lines 2071-2072): Ignore empty uploaded history files
Files Changed
modules/chat.py: Added 3 guard clauses for empty file handling
Screenshot
⚠️ AI-Assisted Fix Disclaimer This fix was written with AI assistance. I do not have programming expertise to fully verify the correctness and completeness of these changes. Please review and test thoroughly before merging. Specifically:
- The fix handles the symptom (empty files) but may not address why llama.cpp creates 0-byte files in the first place
- Edge cases around concurrent file access or race conditions may exist
- The background cleanup script is a workaround, not a root cause fix
- Community testing with various llama.cpp server versions and configurations is needed
- Due to that, I won't push that codes changed to PR
Your verification and feedback are greatly appreciated.
Logs
Traceback (most recent call last):
File "G:\textgen-main\installer_files\env\Lib\site-packages\gradio\queueing.py", line 549, in process_events
response = await route_utils.call_process_api(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<5 lines>...
)
^
File "G:\textgen-main\installer_files\env\Lib\site-packages\gradio\route_utils.py", line 276, in call_process_api
output = await app.get_blocks().process_api(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<11 lines>...
)
^
File "G:\textgen-main\installer_files\env\Lib\site-packages\gradio\blocks.py", line 1904, in process_api
result = await self.call_function(
^^^^^^^^^^^^^^^^^^^^^^^^^
...<8 lines>...
)
^
File "G:\textgen-main\installer_files\env\Lib\site-packages\gradio\blocks.py", line 1490, in call_function
prediction = await anyio.to_thread.run_sync(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fn, *processed_input, limiter=self.limiter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "G:\textgen-main\installer_files\env\Lib\site-packages\anyio\to_thread.py", line 63, in run_sync
return await get_async_backend().run_sync_in_worker_thread(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
func, args, abandon_on_cancel=abandon_on_cancel, limiter=limiter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "G:\textgen-main\installer_files\env\Lib\site-packages\anyio\_backends\_asyncio.py", line 2518, in run_sync_in_worker_thread
return await future
^^^^^^^^^^^^
File "G:\textgen-main\installer_files\env\Lib\site-packages\anyio\_backends\_asyncio.py", line 1002, in run
result = context.run(func, *args)
File "G:\textgen-main\installer_files\env\Lib\site-packages\gradio\\\utils.py", line 812, in wrapper
response = f(*args, **kwargs)
File "G:\textgen-main\modules\chat.py", line 2546, in handle_start_new_chat_click
histories = find_all_histories_with_first_prompts(state)
File "G:\textgen-main\modules\chat.py", line 1906, in find_all_histories_with_first_prompts
data = json.loads(file_content)
File "G:\textgen-main\installer_files\env\Lib\json\__init__.py", line 352, in loads
return _default_decoder.decode(s)
~~~~~~~~~~~~~~~~~~~~~~~^^^
File "G:\textgen-main\installer_files\env\Lib\json\decoder.py", line 345, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "G:\textgen-main\installer_files\env\Lib\json\decoder.py", line 363, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
System Info
Windows 11 Pro Workstation
Gunnir Intel Arc B580 Graphics
Intel i5-14600k
Source: oobabooga/textgen