{"record":{"id":"cb43f49a77fe1216","repo":"FoundationAgents/MetaGPT","slug":"table-not-created-yet-please-add-data-first-cb43f4","errorCode":null,"errorMessage":"Table not created yet, please add data first","messagePattern":"Table not created yet, please add data first","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"metagpt/document_store/lancedb_store.py","lineNumber":77,"sourceCode":"            self.table = self.db.create_table(self.name, documents)\n\n    def add(self, data, metadata, _id):\n        # This function is for adding individual documents\n        # It assumes you're passing in a single vector embedding, metadata, and id\n\n        row = {\"vector\": data, \"id\": _id}\n        row.update(metadata)\n\n        if self.table is not None:\n            self.table.add([row])\n        else:\n            self.table = self.db.create_table(self.name, [row])\n\n    def delete(self, _id):\n        # This function deletes a row by id.\n        # LanceDB delete syntax uses SQL syntax, so you can use \"in\" or \"=\"\n        if self.table is None:\n            raise Exception(\"Table not created yet, please add data first\")\n\n        if isinstance(_id, str):\n            return self.table.delete(f\"id = '{_id}'\")\n        else:\n            return self.table.delete(f\"id = {_id}\")\n\n    def drop(self, name):\n        # This function drops a table, if it exists.\n\n        path = os.path.join(self.db.uri, name + \".lance\")\n        if os.path.exists(path):\n            shutil.rmtree(path)\n","sourceCodeStart":59,"sourceCodeEnd":90,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/document_store/lancedb_store.py#L59-L90","documentation":"LanceStore.delete raises a plain Exception when self.table is None. Deletion requires an existing table, which is only created by a prior successful add(); calling delete on a store that never ingested data has nothing to delete and the wrapper rejects it explicitly rather than silently succeeding.","triggerScenarios":"Calling store.delete(_id) on a LanceStore instance where add() was never called, or after the table was dropped. The id is formatted into a SQL filter ('id = ...' or \"id = '...'\") and passed to table.delete.","commonSituations":"Cleanup/rerank scripts that delete stale vectors before ingestion runs; a new process pointing at an existing db path but never reopening the table; test teardown deleting from a store that the test never populated.","solutions":["Ensure add() ran at least once in this process, or reopen the persisted table: store.table = store.db.open_table(store.name).","Guard deletion: if store.table is None: skip or log, since there is nothing to delete.","Verify the table exists via db.table_names() before constructing the store's delete path."],"exampleFix":"# before\nstore.delete(\"doc-42\")  # Exception: Table not created yet\n\n# after\nif store.table is not None:\n    store.delete(\"doc-42\")\nelse:\n    logger.info(\"nothing to delete, table does not exist\")","handlingStrategy":"validation","validationCode":"def safe_delete(store, _id):\n    if store.table is None:\n        return False  # nothing ingested, nothing to delete\n    store.delete(_id)\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    store.delete(_id)\nexcept Exception as e:\n    if \"Table not created yet\" not in str(e):\n        raise  # only swallow the empty-store case","preventionTips":["Guard cleanup code with `if store.table is None: return` — deleting from an empty store is a no-op by definition.","Make teardown idempotent so reruns never assume prior state.","Reopen persisted tables (db.open_table) when a fresh process must delete previously stored rows."],"tags":["python","lancedb","vector-store","initialization-order"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}