Skip to content

fix(meta): skip unrecognized table index type in TableMeta deserialization#20115

Open
vismaytiwari wants to merge 1 commit into
databendlabs:mainfrom
vismaytiwari:fix-skip-unknown-table-index-type
Open

fix(meta): skip unrecognized table index type in TableMeta deserialization#20115
vismaytiwari wants to merge 1 commit into
databendlabs:mainfrom
vismaytiwari:fix-skip-unknown-table-index-type

Conversation

@vismaytiwari

@vismaytiwari vismaytiwari commented Jul 7, 2026

Copy link
Copy Markdown

I hereby agree to the terms of the CLA available at: https://docs.databend.com/dev/policies/cla/

Summary

TableMeta::from_pb deserializes every index eagerly, and TableIndex::from_pb
returns Incompatible when TableIndexType::from_i32 does not recognize the
stored discriminant (src/meta/proto-conv/src/impls/table.rs). So once a table
enables an index type that a given binary does not know about — e.g. a table
created by a newer version that added a new index type — that binary can no
longer read the entire table metadata, not just the unknown index.

This skips indexes whose type is not recognized so the rest of the metadata
still loads and the table stays readable. Recognized indexes and any other
incompatibilities are unaffected.

Reproduced with test_table_meta_skips_unknown_index_type: a TableMeta with a
valid index plus one carrying an unrecognized index_type fails from_pb with
invalid IndexType: 9999 before the change; after it, deserialization succeeds
and only the unknown index is dropped.

Tests

  • Unit Test
  • Logic Test
  • Benchmark Test
  • No Test - Explain why

Type of change

  • Bug Fix (non-breaking change which fixes an issue)
  • New Feature (non-breaking change which adds functionality)
  • Breaking Change (fix or feature that could cause existing functionality not to work as expected)
  • Documentation Update
  • Refactoring
  • Performance Improvement
  • Other (please describe):

This change is Reviewable

…ation

TableMeta::from_pb deserializes every index eagerly, and TableIndex::from_pb
returns Incompatible when TableIndexType::from_i32 does not recognize the stored
discriminant. So once a table enables an index type a given binary does not know
(e.g. a newer version added one), that binary fails to read the entire table
metadata instead of just skipping the unknown index.

Skip indexes whose type is not recognized so the rest of the metadata still
loads. Recognized indexes and other incompatibilities are unaffected.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 65d1179fda

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// Skip indexes whose type this binary does not recognize, so a table
// that enables a newer index type can still be read by an older binary
// instead of failing to deserialize the whole TableMeta (#20113).
.filter(|(_, index)| mt::TableIndexType::from_i32(index.index_type).is_some())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve unknown indexes before accepting writes

When this runs on an older/rolling-upgrade binary against a table that contains a future index type, the filter removes that entry from TableMeta before the in-memory value is returned. Any later metadata write of the same table, even an unrelated one such as upsert_table_option mutating seq_meta.data and writing it back with txn_put_pb, will serialize the filtered map and permanently delete the newer index metadata. Either preserve the raw unknown entries through round-trip serialization or reject writes when unknown indexes were present instead of silently dropping them during deserialization.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — this is real. My patch lets an older binary read the table, but since reads round-trip through from_pb/to_pb (e.g. upsert_table_option mutates seq_meta.data and writes it back), dropping the unknown index on read means a later unrelated write silently deletes it — arguably worse than the original hard failure, which at least didn't lose data. Doing this safely means either preserving the raw unknown entries through the round-trip so to_pb re-emits them, or rejecting writes when unknown indexes were present — both reach beyond this deserialization spot into TableMeta. @zhang2014 which would you prefer? Happy to implement it.

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

Labels

pr-bugfix this PR patches a bug in codebase

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Unknown index type in TableIndexType causes hard Incompatible failure on older Databend versions

1 participant