Skip to content

Never cache a table for a document that could not be read - #187

Merged
MikeAlhayek merged 1 commit into
mainfrom
claude/tabular-empty-import-fix
Sep 14, 2026
Merged

MikeAlhayek merged 1 commit into
mainfrom
claude/tabular-empty-import-fix

Conversation

@MikeAlhayek

Copy link
Copy Markdown
Member

Fixes a regression reported right after #186 merged: the model reports that uploaded workbooks "are showing only placeholder columns with no data rows" and asks the user to re-upload, on a conversation that had been answering questions about those same files minutes earlier.

Cause

A document whose content could not be loaded was still turned into a table.

FromDelimitedContent returns an empty artifact for empty content, and CreateTable answers an empty header by creating a placeholder table — one "value" TEXT column, no rows. That table was then written to _workspace_meta, which made IsDocumentLoaded return true for the rest of the conversation. The workspace served the empty table from then on and never read the file again. Re-uploading was the only way out, which is exactly what the model told the user to do.

Reproduced directly: a document whose loader returns no content yields a table named after the file with columns [value] and rows=0, persisted in the metadata.

The placeholder-caching bug predates #186. What #186 changed is that detached documents' tables are now pruned, so a stale-but-populated table is no longer left sitting there to answer questions — which is what made this reachable.

Fix

  • An import that yields no content registers nothing, so the next request retries instead of caching emptiness permanently.
  • An importer that returns no tables falls through to the artifact loader rather than marking the document done, so a failed streaming import still gets a second chance.
  • TabularToolRunner says the files could not be read instead of handing back an empty workspace, which reads to the model as files that legitimately contain no data.

Databases already in this state repair themselves

A table with the single placeholder column and no rows is dropped on the next request and its document imported again — no re-upload needed.

The row check is what makes that safe to act on. A table the user emptied through the manipulation tool keeps the real columns of its source file, so a deliberate edit can never match the placeholder shape; and re-importing something that does match cannot lose data, because it holds none. There is a test for each half of that.

Tests

Five new tests: no table created when content is unavailable; the import retried once content is available; one failing document not taking down the documents that loaded; a database already holding a placeholder table recovering on the next request; and a user-emptied table not being re-imported.

Verified non-vacuous — with the fix reverted, 4 of the 5 fail on the exact symptom. Full suite: 3269 passed, 0 failed.

🤖 Generated with Claude Code

A document whose content could not be loaded was still turned into a table.
FromDelimitedContent returns an empty artifact for empty content, and
CreateTable answers an empty header with a placeholder "value" column and no
rows. That table was then written to _workspace_meta, which made
IsDocumentLoaded true for the rest of the conversation: the workspace served
an empty table from then on and never read the file again. The model saw
files with a placeholder column and no data and told the user to upload them
again, which was the only way out.

An import that yields no content now registers nothing, so the next request
tries again, and an importer that returns no tables falls through to the
artifact loader instead of marking the document done. TabularToolRunner says
the files could not be read rather than handing back an empty workspace,
which reads to the model as files that contain no data.

Databases already holding one of these tables repair themselves: a table with
the single placeholder column and no rows is dropped on the next request and
its document imported again. The row check is what makes that safe to act on.
A table emptied through the manipulation tool keeps the real columns of its
source file, so a deliberate edit can never match, and re-importing something
that does match cannot lose data because it holds none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@MikeAlhayek
MikeAlhayek merged commit bf797ec into main Sep 14, 2026
9 checks passed
@MikeAlhayek
MikeAlhayek deleted the claude/tabular-empty-import-fix branch September 14, 2026 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant