8000 [BUG] Failed MCP seed_table calls erase existing table data before validating the replacement · Issue #57 · dmux/minilake · GitHub
[go: up one dir, main page]

Skip to content

[BUG] Failed MCP seed_table calls erase existing table data before validating the replacement #57

Closed

Description

@eddiethedean

Description

seed_table commits destructive changes before validating or inserting the replacement data. An ordinary invalid value causes the tool to return an error after deleting all existing rows. With recreate=true, an invalid column type drops the entire existing table before returning the validation error.

Verified against MiniLake 1.9.0 source at local commit e24f46a7753ff0be30df3d83978c370c817f89cd (based on upstream fe8837dcfac9df621dfabc440abc07ebb4cdbcbb; the affected code is unchanged). Reproduced using a real disposable HTTP server and fresh data, with Python 3.14.3, DuckDB 1.5.6, FastAPI 0.162.0 and, for MCP, mcp 1.30.0. No mocks or user data were used.

Affected Components

Steps to Reproduce

Start a disposable instance with MINILAKE_MCP=1. Use an initialized MCP client session against /mcp.

  1. Call seed_table with:
    {"full_name":"seed_guard.s.t","columns":[{"name":"id","type_text":"INT"}],"rows":[[41],[42]]}
  2. Verify SELECT * FROM seed_guard.s.t returns rows 41 and 42.
  3. Call seed_table again with:
    {"full_name":"seed_guard.s.t","columns":[{"name":"id","type_text":"INT"}],"rows":[["not an integer"]]}
  4. Query the table after the tool error.
  5. Restore the original two rows using step 1, then call:
    {"full_name":"seed_guard.s.t","columns":[{"name":"id","type_text":"NOT_A_TYPE"}],"rows":[[41]],"recreate":true}
  6. Query the table after the second error.

These calls were verified using the real MCP SDK over Streamable HTTP and the real DuckDB-backed Statement Execution path.

Expected Behavior

Reject an invalid replacement without losing the existing table/data. Validate column types and replacement rows before destructive changes, and make the replacement atomic.

Actual Behavior

  • Step 3 returns isError=true with Conversion Error: Could not convert string 'not an integer' to INT32. The original table is now empty: [].
  • Step 5 returns an unsupported-column-type error. The subsequent SELECT fails because the original table has been dropped.

Root Cause Analysis

The normal path sends an autocommitted DELETE before sending a separate INSERT. An INSERT error cannot roll back the earlier DELETE. The recreate path sends DROP TABLE and removes metadata before the create endpoint validates the new schema. There is no staging or transaction encompassing the replacement.

Impact

A failed fixture/data refresh destroys a previously valid dataset. A model or developer can correct the input after receiving an error, but the original data is already lost. This is real on-disk data loss in the supported local workflow, not merely an incorrect result message.

Suggested Fix

Validate the requested schema, row arity and value conversions first. Build and populate a staging table before replacing the target, or execute validated deletion/insertion in one locked transaction for the relevant catalog. For recreate, retain the original physical table and metadata until the replacement is ready; roll back both on failure.

Test Coverage Gaps

MCP tests cover successful seed calls, quote escaping, malformed names and invalid types when creating a new table. Add invalid values/types/row counts while replacing a populated 56AB table, with and without recreate, and assert the original schema, metadata and rows survive each failure.

Severity

High

Confidence

High — both destructive failure paths reproduced through the real MCP protocol.

Recommended Labels

bug, high-priority

Existing Issue Matches

No reasonable duplicate found. Reviewed all open issues, the closed-issue search (no results), and all open PRs, then searched the affected functions/components and symptoms. Open PR #54 fixes duplicate Arrow columns only; #29 updates virtualenv. Neither addresses this defect. The documented local/single-user limitations were checked. Searches included seed_table, MCP, rollback, transaction, INSERT and replacement data loss.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0