Chats are not loading

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

It was working very well and perfectly, but it often froze when planning the next stage. So I restarted the program, and after that the chats stopped working.

Steps to Reproduce

It was working very well and perfectly, but it often froze when planning the next stage. So I restarted the program, and after that the chats stopped working.

Operating System

Windows 10/11

Version Information

Version: 2.4.21 (user setup)
VSCode Version: 1.105.1
Commit: dc8361355d709f306d5159635a677a571b277bc0
Date: 2026-01-22T16:57:59.675Z
Build Type: Stable
Release Track: Default
Electron: 39.2.7
Chromium: 142.0.7444.235
Node.js: 22.21.1
V8: 14.2.231.21-electron.0
OS: Windows_NT x64 10.0.19045

For AI issues: which model did you use?

opus 4.5

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

No request ID found

After restarting, it asked me to log in as if I were using it for the first time, and I think some settings were deleted.

Hey, thanks for the report. This is a known issue in v2.4.21. After a crash or restart, the auth token can become invalid. That can force a re-login and can break chat loading.

Step 1: Fix chat loading

Sign out and sign back in: Cursor Settings > Sign Out > Sign In. This refreshes your auth token.

Step 2: Try to recover your data

Cursor creates automatic backups, which can help. Here’s how to check:

  1. Fully close Cursor (confirm in Task Manager)
  2. Open this folder: %APPDATA%\Cursor\User\globalStorage
  3. Look for these files:
    • state.vscdb (current DB, likely corrupted or empty)
    • state.vscdb.backup (automatic backup)
    • state.vscdb.corrupted.XXXXX... (your data marked as corrupted after the crash)

If you found a .corrupted file (best chance to recover):

  1. Rename state.vscdb to state.vscdb.old
  2. Rename the .corrupted file to state.vscdb
  3. Start Cursor

If you only have .backup:

  1. Rename state.vscdb to state.vscdb.old
  2. Rename state.vscdb.backup to state.vscdb
  3. Start Cursor

There’s also a detailed tutorial with a PowerShell script that automates this process: Tutorial: How to Fix "Loading Chat" and Recover History (Cursor v2.3.x)

To prevent this in the future:

Periodically back up these paths:

  • %APPDATA%\Cursor\User\globalStorage\state.vscdb
  • %APPDATA%\Cursor\User\workspaceStorage

By the way, how much free disk space do you have? Low free space can trigger issues like this.

Let me know which files you found in that folder and whether you were able to recover anything.

1 Like

here is a script. put it in a fresh cursor file with your state.vcsdb file. ~/Library/Application Support/Cursor/User/globalStorage/ <on Mac

the script will pull out all your chats with code changes and chat names into a folder. just have chat run it for you.

#!/usr/bin/env python3

import sqlite3

import json

import os

import re

from datetime import datetime

# Database path

db_path = “/Users/passes/Library/Application Support/Cursor/User/globalStorage/state.vscdb”

output_dir = “/Users/passes/Desktop/Passes CRM/cursor-chats-complete”

# Ensure output directory exists

os.makedirs(output_dir, exist_ok=True)

# Connect to database

conn = sqlite3.connect(db_path)

cursor = conn.cursor()

def sanitize_filename(name):

name = re.sub(r'\[<>:"/\\\\|?\*\]', '', name)

name = name.replace(' ', '\_')

return name[:100]

print(“=” * 70)

print(“EXTRACTING COMPLETE CURSOR CONVERSATIONS”)

print(“=” * 70)

# Step 1: Get all composer data with names and conversation info

print(“\nStep 1: Loading composer metadata…”)

cursor.execute(“SELECT key, value FROM cursorDiskKV WHERE key LIKE ‘composerData:%’”)

composer_data_rows = cursor.fetchall()

composers = {}

for key, value in composer_data_rows:

try:

    data = json.loads(value)

    composer_id = data.get('composerId')

    name = data.get('name', 'Untitled Chat')

    created_at = data.get('createdAt')

    conversation_headers = data.get('fullConversationHeadersOnly', \[\])

    composers\[composer_id\] = {

‘name’: name,

‘created_at’: created_at,

‘bubble_ids’: [h.get(‘bubbleId’) for h in conversation_headers if ‘bubbleId’ in h],

‘data’: data

    }

except Exception as e:

pass

print(f" Found {len(composers)} composer conversations")

# Step 2: Get all bubbles (messages)

print(“\nStep 2: Loading all message bubbles…”)

cursor.execute(“SELECT key, value FROM cursorDiskKV WHERE key LIKE ‘bubbleId:%’”)

bubble_rows = cursor.fetchall()

# Organize bubbles by composer

bubbles_by_composer = {}

for key, value in bubble_rows:

try:

# Key format: bubbleId::

    parts = key.split(':')

if len(parts) >= 3:

        composer_id = parts\[1\]

        bubble_id = parts\[2\]

if composer_id not in bubbles_by_composer:

            bubbles_by_composer\[composer_id\] = {}

        bubble_data = json.loads(value)

        bubbles_by_composer\[composer_id\]\[bubble_id\] = bubble_data

except Exception as e:

pass

print(f" Found {len(bubble_rows)} message bubbles across {len(bubbles_by_composer)} composers")

# Step 3: Export each conversation

print(“\nStep 3: Exporting complete conversations…\n”)

exported_count = 0

for idx, (composer_id, composer_info) in enumerate(sorted(composers.items(), key=lambda x: x[1].get(‘created_at’, 0), reverse=True), 1):

name = composer_info\['name'\]

created_at = composer_info\['created_at'\]

bubble_ids = composer_info\['bubble_ids'\]

# Skip if no bubbles

if not bubble_ids or composer_id not in bubbles_by_composer:

continue

# Get all bubbles for this conversation

composer_bubbles = bubbles_by_composer.get(composer_id, {})

# Create filename

safe_name = sanitize_filename(name) *if* name and name not in \['New Chat', 'Chat'\] *else* f"chat\_{composer_id\[:16\]}"

filename = f"{idx:03d}\_{safe_name}.md"

filepath = os.path.join(output_dir, filename)

# Build the conversation

with open(filepath, ‘w’, encoding=‘utf-8’) as f:

    f.write(f"# {name}\\n\\n")

    f.write(f"\*\*Composer ID:\*\* \`{composer_id}\`\\n")

if created_at:

        dt = datetime.fromtimestamp(created_at / 1000)

        f.write(f"\*\*Created:\*\* {dt.strftime('%Y-%m-%d %H:%M:%S')}\\n")

    f.write(f"\*\*Messages:\*\* {len(bubble_ids)}\\n\\n")

    f.write("---\\n\\n")

# Write each message

    message_count = 0

for bubble_id in bubble_ids:

if bubble_id not in composer_bubbles:

continue

        bubble = composer_bubbles\[bubble_id\]

        msg_type = bubble.get('type')

        text = bubble.get('text', '')

        rich_text = bubble.get('richText', '')

# Type 1 = User, Type 2 = Assistant

if msg_type == 1:

            f.write(f"## 👤 User\\n\\n")

elif msg_type == 2:

            f.write(f"## 🤖 Assistant\\n\\n")

else:

            f.write(f"## Message (type {msg_type})\\n\\n")

# Write the message content

if text:

            f.write(f"{text}\\n\\n")

            message_count += 1

elif rich_text:

# Rich text might be JSON, try to extract readable content

try:

if isinstance(rich_text, str):

                    rich_data = json.loads(rich_text)

else:

                    rich_data = rich_text

                f.write(f"\`\`\`json\\n{json.dumps(rich_data, *indent*=2)\[:1000\]}...\\n\`\`\`\\n\\n")

except:

                f.write(f"{str(rich_text)\[:500\]}...\\n\\n")

        f.write("---\\n\\n")

if message_count > 0:

        exported_count += 1

print(f" ✓ {idx:03d}. {name[:60]:<60} ({message_count} messages)")

print(f"\n​:white_check_mark: Exported {exported_count} complete conversations")

# Step 4: Create an index

print(“\nStep 4: Creating index…”)

index_path = os.path.join(output_dir, “00_INDEX.md”)

with open(index_path, ‘w’, encoding=‘utf-8’) as f:

f.write("# Cursor Conversations Index\\n\\n")

f.write(f"\*\*Exported:\*\* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\\n")

f.write(f"\*\*Total Conversations:\*\* {exported_count}\\n\\n")

f.write("---\\n\\n")

for idx, (composer_id, composer_info) in enumerate(sorted(composers.items(), key=lambda x: x[1].get(‘created_at’, 0), reverse=True), 1):

    name = composer_info\['name'\]

    created_at = composer_info\['created_at'\]

    bubble_ids = composer_info\['bubble_ids'\]

if not bubble_ids or composer_id not in bubbles_by_composer:

continue

    composer_bubbles = bubbles_by_composer.get(composer_id, {})

    message_count = sum(1 *for* bid *in* bubble_ids *if* bid *in* composer_bubbles *and* composer_bubbles\[bid\].get('text'))

if message_count > 0:

        safe_name = sanitize_filename(name) *if* name and name not in \['New Chat', 'Chat'\] *else* f"chat\_{composer_id\[:16\]}"

        filename = f"{idx:03d}\_{safe_name}.md"

        f.write(f"## {idx}. {name}\\n\\n")

        f.write(f"- \*\*File:\*\* \`{filename}\`\\n")

        f.write(f"- \*\*Messages:\*\* {message_count}\\n")

if created_at:

            dt = datetime.fromtimestamp(created_at / 1000)

            f.write(f"- \*\*Created:\*\* {dt.strftime('%Y-%m-%d %H:%M:%S')}\\n")

        f.write("\\n")

print(f":white_check_mark: Created index: 00_INDEX.md")

conn.close()

print(“\n” + “=” * 70)

print(“EXPORT COMPLETE!”)

print(“=” * 70)

print(f"\n​:file_folder: Location: {output_dir}")

print(f":memo: {exported_count} conversations exported with full message history")

print(f":clipboard: Index file: 00_INDEX.md")