{"record":{"id":"9ae4f948f70b2ac3","repo":"mvanhorn/last30days-skill","slug":"library-search-requires-a-python-sqlite-build-with","errorCode":null,"errorMessage":"library search requires a Python SQLite build with FTS5 support","messagePattern":"library search requires a Python SQLite build with FTS5 support","errorType":"exception","errorClass":"LibrarySearchUnavailable","httpStatus":null,"severity":"warning","filePath":"skills/last30days/scripts/lib/library_index.py","lineNumber":109,"sourceCode":"\ndef fts5_available() -> bool:\n    try:\n        with sqlite3.connect(\":memory:\") as conn:\n            conn.execute(\"CREATE VIRTUAL TABLE probe USING fts5(value)\")\n    except sqlite3.DatabaseError:\n        return False\n    return True\n\n\ndef sync_library(\n    memory_dir: Path | str = library.DEFAULT_MEMORY_DIR,\n    briefs_dir: Path | str = library.DEFAULT_BRIEFS_DIR,\n    *,\n    db_path: Path | str = DEFAULT_LIBRARY_DB,\n) -> SyncResult:\n    \"\"\"Incrementally index the shared ``scan_library`` view of saved research.\"\"\"\n    if not fts5_available():\n        raise LibrarySearchUnavailable(\n            \"library search requires a Python SQLite build with FTS5 support\"\n        )\n    target = Path(db_path).expanduser()\n    try:\n        return _sync_library(memory_dir, briefs_dir, target)\n    except sqlite3.DatabaseError as exc:\n        if \"fts5\" in str(exc).lower() and \"malformed\" not in str(exc).lower():\n            raise LibrarySearchUnavailable(\n                \"library search requires a Python SQLite build with FTS5 support\"\n            ) from exc\n        if not _is_confirmed_corruption(exc):\n            raise\n        _remove_database(target)\n        return replace(_sync_library(memory_dir, briefs_dir, target), rebuilt=True)\n\n\ndef index_brief(\n    path: Path | str,","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/library_index.py#L91-L127","documentation":"Raised by sync_library in library_index.py as LibrarySearchUnavailable when fts5_available() returns False at entry — i.e. the interpreter's sqlite3 module was built without FTS5 full-text search support. Library search is implemented as an SQLite FTS5 index, so the feature is hard-unavailable on such builds; the dedicated exception type lets callers degrade gracefully instead of crashing.","triggerScenarios":"Calling sync_library / the library-search command on Python builds where FTS5 was not compiled in: some distro Pythons, minimal/stripped SQLite builds, older Python versions, or systems linking against a system libsqlite3 without FTS5. Verify with: python -c \"import sqlite3; c=sqlite3.connect(':memory:'); c.execute('CREATE VIRTUAL TABLE t USING fts5(x)')\".","commonSituations":"Alpine/BusyBox-based containers with a lean sqlite; macOS system Python variants; corporate images with a custom-compiled SQLite; upgrading the OS swapped the linked libsqlite3 to one without FTS5.","solutions":["Use a Python/SQLite build with FTS5: official python.org builds and most conda/uv pythons include it; on Debian/Ubuntu ensure libsqlite3 is full-featured; on Alpine use a build with SQLITE_ENABLE_FTS5.","Catch LibrarySearchUnavailable and skip/notify rather than fail the whole run — scan_library (plain listing) works without FTS5.","Confirm the diagnosis first: python -c \"import sqlite3;print(sqlite3.sqlite_version)\" plus the CREATE VIRTUAL TABLE probe above."],"exampleFix":"# before\nfrom last30days.scripts.lib.library_index import sync_library\nsync_library()\n\n# after\nfrom last30days.scripts.lib.library_index import sync_library, LibrarySearchUnavailable\ntry:\n    sync_library()\nexcept LibrarySearchUnavailable:\n    print(\"library search disabled: this Python lacks SQLite FTS5\")","handlingStrategy":"try-catch","validationCode":"import sqlite3\n\ndef fts5_available() -> bool:\n    try:\n        conn = sqlite3.connect(\":memory:\")\n        conn.execute(\"CREATE VIRTUAL TABLE probe USING fts5(x)\")\n        conn.close()\n        return True\n    except sqlite3.Error:\n        return False","typeGuard":null,"tryCatchPattern":"from skills.last30days.scripts.lib.library_index import sync_library, LibrarySearchUnavailable\n\ntry:\n    sync_library(memory_dir, briefs_dir)\nexcept LibrarySearchUnavailable:\n    logging.warning(\"library search disabled on this Python (no SQLite FTS5); listing still works\")","preventionTips":["Probe FTS5 once at install time and record the result per environment.","Use python.org, conda, or uv-managed Python builds — they bundle FTS5-enabled SQLite.","Design callers to degrade to scan_library listing when LibrarySearchUnavailable is raised."],"tags":["sqlite","fts5","environment","library"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}