{"record":{"id":"44a7cdc18c2f4161","repo":"databendlabs/databend","slug":"operation-asis-is-not-supported","errorCode":null,"errorMessage":"Operation::AsIs is not supported","messagePattern":"Operation::AsIs is not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/api/src/kv/pb_api/compress.rs","lineNumber":68,"sourceCode":"\nimpl Encoder {\n    pub const fn new(compress: bool) -> Self {\n        Self {\n            compress: AtomicBool::new(compress),\n        }\n    }\n\n    pub fn set_compress(&self, compress: bool) {\n        self.compress.store(compress, Ordering::Relaxed);\n    }\n\n    /// Encode an upsert Operation of T into protobuf encoded value.\n    pub fn encode_operation<T: FromToProto>(&self, value: &Operation<T>) -> Operation<Vec<u8>> {\n        match value {\n            Operation::Update(t) => Operation::Update(self.encode_pb(t)),\n            Operation::Delete => Operation::Delete,\n            _ => {\n                unreachable!(\"Operation::AsIs is not supported\")\n            }\n        }\n    }\n\n    /// Encode a `FromToProto` value to protobuf bytes, with optional zstd compression.\n    pub fn encode_pb<T: FromToProto>(&self, value: &T) -> Vec<u8> {\n        let p = value.to_pb();\n        self.encode_value(prost::Message::encode_to_vec(&p))\n    }\n\n    /// Optionally compress `buf` with zstd.\n    ///\n    /// Returns `buf` unchanged if compression is disabled or `buf.len() < COMPRESS_THRESHOLD`.\n    /// Otherwise prepends `[0x0F, FLAG_ZSTD, 0x00, 0x00]` and returns the compressed payload.\n    /// Falls back to returning `buf` uncompressed on compression error.\n    pub fn encode_value(&self, buf: Vec<u8>) -> Vec<u8> {\n        if !self.compress.load(Ordering::Relaxed) {\n            return buf;","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/meta/api/src/kv/pb_api/compress.rs#L50-L86","documentation":"encode_operation converts a typed Operation<T> into its protobuf-encoded Operation<Vec<u8>>, and it only supports Update and Delete. Operation::AsIs (a directive meaning 'leave the existing value untouched') cannot be encoded into a value-carrying upsert, so reaching the match wildcard panics. The API contract is that callers must only pass Update or Delete to this encoder.","triggerScenarios":"Calling encode_operation (directly or via an upsert/SafeUpload path) with an Operation that is Operation::AsIs — e.g. generic meta write code that copies a caller-supplied Operation without normalizing AsIs first.","commonSituations":"New meta API code reusing encode_operation with share/AsIs-style semantics; refactors that forward Operations from higher layers without filtering; misuse of the pb_api by extension code.","solutions":["Do not pass Operation::AsIs to encode_operation; handle AsIs at the caller level (skip the write or resolve it to an explicit value first)","Match on the operation before encoding: return Operation::AsIs passthrough or an error for unsupported variants","If you need AsIs semantics, use a transaction API that natively supports the AsIs operation instead of the pb encoder","Audit call sites of encode_operation and add debug asserts/tests that reject AsIs early"],"exampleFix":"// before\nlet encoded = sm.encode_operation(&op); // panics if op == AsIs\n// after\nlet encoded = match op {\n    Operation::Update(_) | Operation::Delete => sm.encode_operation(&op),\n    Operation::AsIs => return Err(ErrorCode::InternalError(\"AsIs not encodable\")),\n};","handlingStrategy":"type-guard","validationCode":"if matches!(op, Operation::AsIs) { return Err(ErrorCode::InternalError(\"AsIs not supported by encode_operation\")); }","typeGuard":"fn is_encodable<T>(op: &Operation<T>) -> bool { !matches!(op, Operation::AsIs) }","tryCatchPattern":"// not a catchable error: it panics. Guard instead:\nassert!(!matches!(op, Operation::AsIs), \"AsIs must be resolved before encoding\");","preventionTips":["Resolve Operation::AsIs to a concrete value before calling pb encoders","Add unit tests asserting encode_operation rejects/handles AsIs","Use txn APIs that natively support AsIs when needed"],"tags":["rust","meta-service","protobuf","unsupported-operation"],"backgroundTag":"unsupported-enum-value","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}