# Telethon Session Repair — Full Recipes Real repair scripts used in production. Copy-paste and run. ## Fix 7-column → 6-column (drop `number`) Two 7-column variants exist. ALWAYS check actual column names first. ### Variant A: `number` column (Telethon v2, 2026+) Columns: `dc_id, server_address, port, auth_key, takeout_id, tmp_auth_key, number` Drop the extra `number` column: ```python import sqlite3, shutil from pathlib import Path SESSION_DIR = Path("sessions_clean") for f in SESSION_DIR.glob("*.session"): db = sqlite3.connect(str(f)) cur = db.execute("PRAGMA table_info(sessions)") cols = [r[1] for r in cur.fetchall()] db.close() if len(cols) == 7 and "number" in cols: shutil.copy(str(f), str(f) + ".bak7cols") db = sqlite3.connect(str(f)) db.execute(""" CREATE TABLE sessions_new ( dc_id INT PRIMARY KEY, server_address TEXT, port INT, auth_key BLOB, takeout_id INTEGER, tmp_auth_key BLOB ) """) db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, takeout_id, tmp_auth_key FROM sessions") db.execute("DROP TABLE sessions") db.execute("ALTER TABLE sessions_new RENAME TO sessions") db.commit() db.close() print(f"Fixed: {f.name}") ``` ### Variant B: `auth_key_id` column (older) Columns: `dc_id, server_address, port, auth_key, auth_key_id, takeout_id, tmp_auth_key` Drop the extra `auth_key_id` column: ```python import sqlite3, shutil from pathlib import Path for f in Path("sessions_clean").glob("*.session"): db = sqlite3.connect(str(f)) cur = db.execute("PRAGMA table_info(sessions)") cols = [r[1] for r in cur.fetchall()] db.close() if len(cols) == 7 and "auth_key_id" in cols: shutil.copy(str(f), str(f) + ".bak7cols") db = sqlite3.connect(str(f)) db.execute(""" CREATE TABLE sessions_new ( dc_id INT, server_address TEXT, port INT, auth_key BLOB, takeout_id INTEGER, tmp_auth_key BLOB ) """) db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, takeout_id, tmp_auth_key FROM sessions") db.execute("DROP TABLE sessions") db.execute("ALTER TABLE sessions_new RENAME TO sessions") db.commit() db.close() print(f"Fixed: {f.name}") ``` ## Fix 5-column → 6-column Two 5-column variants exist. ALWAYS check the actual column names before repairing. ### Variant A: missing `takeout_id` (cols: `dc_id, server_address, port, auth_key, auth_key_id`) Older Telethon v7 sessions. Add `takeout_id` as NULL. ```python import sqlite3, shutil from pathlib import Path for f in Path("sessions_clean").glob("*.session"): db = sqlite3.connect(str(f)) cur = db.execute("PRAGMA table_info(sessions)") cols = [r[1] for r in cur.fetchall()] db.close() if len(cols) == 5 and "auth_key_id" in cols: shutil.copy(str(f), str(f) + ".bak5cols") db = sqlite3.connect(str(f)) db.execute(""" CREATE TABLE sessions_new ( dc_id INT, server_address TEXT, port INT, auth_key BLOB, auth_key_id BLOB, takeout_id INTEGER ) """) db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, auth_key_id, NULL FROM sessions") db.execute("DROP TABLE sessions") db.execute("ALTER TABLE sessions_new RENAME TO sessions") db.commit() db.close() print(f"Fixed: {f.name}") ``` ### Variant B: missing `auth_key_id` (cols: `dc_id, server_address, port, auth_key, takeout_id`) Encountered on MAINTG1.session (2026-07-28). This schema has `takeout_id` but no `auth_key_id`. Add `auth_key_id` as NULL. ```python # PROVEN on MAINTG1.session (C:\Users\User\Desktop\_PROJECTS\tg_content_agent\) import sqlite3, shutil f = "MAINTG1.session" db = sqlite3.connect(f) cols = [r[1] for r in db.execute("PRAGMA table_info(sessions)")] print(f"Cols: {cols}") # Expected: ['dc_id', 'server_address', 'port', 'auth_key', 'takeout_id'] if len(cols) == 5 and "takeout_id" in cols and "auth_key_id" not in cols: shutil.copy(f, f + ".bak5cols_v2") db.execute(""" CREATE TABLE sessions_new ( dc_id INT, server_address TEXT, port INT, auth_key BLOB, auth_key_id BLOB, takeout_id INTEGER ) """) db.execute("INSERT INTO sessions_new SELECT dc_id, server_address, port, auth_key, NULL, takeout_id FROM sessions") db.execute("DROP TABLE sessions") db.execute("ALTER TABLE sessions_new RENAME TO sessions") db.commit() # Verify new_cols = [r[1] for r in db.execute("PRAGMA table_info(sessions)")] row = db.execute("SELECT * FROM sessions").fetchone() assert len(new_cols) == 6, f"Expected 6 cols, got {len(new_cols)}" print(f"Fixed: {new_cols}, auth_key_len={len(row[3]) if row[3] else 0}") db.close() ``` ## Bulk session health check ```python import sqlite3 from pathlib import Path for d in ["sessions5", "sessions_clean", "session", "sessions_archive"]: sd = Path(d) if not sd.exists(): continue for f in sorted(sd.glob("*.session")): try: db = sqlite3.connect(str(f)) cur = db.execute("PRAGMA table_info(sessions)") cols = [r[1] for r in cur.fetchall()] cur = db.execute("SELECT * FROM sessions") row = cur.fetchone() db.close() status = "OK" if len(cols) == 6 and row and len(row) == 6 else f"BAD cols={len(cols)} row={len(row) if row else 0}" print(f"{d}/{f.stem}: {status}") except Exception as e: print(f"{d}/{f.stem}: ERROR {e}") ``` ## Check for corrupted auth_key (causes `TypeError: Strings must be encoded before hashing`) ```python import sqlite3 from pathlib import Path for d in ["sessions5", "sessions_clean"]: for f in Path(d).glob("*.session"): db = sqlite3.connect(str(f)) cur = db.execute("SELECT auth_key FROM sessions") row = cur.fetchone() db.close() if row and row[0] is not None: ak = row[0] if isinstance(ak, str): print(f"BAD (string auth_key): {f}") elif isinstance(ak, bytes): if len(ak) < 100: print(f"SUSPECT (short auth_key {len(ak)}b): {f}") else: print(f"BAD (type {type(ak).__name__}): {f}") else: print(f"NULL auth_key: {f}") ```