{"record":{"id":"7e8c009bd04d1ade","repo":"bottlerocket-os/bottlerocket","slug":"invalidkeysnafu","errorCode":"InvalidKeySnafu","errorMessage":"Key name '' has invalid format: strip_prefix of '{prefix}' matches key","messagePattern":"Key name '' has invalid format: strip_prefix of '(.+?)' matches key","errorType":"validation","errorClass":"datastore::Error","httpStatus":null,"severity":"error","filePath":"sources/api/datastore/src/key.rs","lineNumber":108,"sourceCode":"    }\n\n    /// Removes the given prefix from the key name, returning a new Key.\n    ///\n    /// This is intended to remove key name segments from the beginning of the name, therefore\n    /// this only makes sense for Data keys, not Meta keys.  A Data key will be returned.\n    ///\n    /// You should not include an ending separator (dot), it will be removed for you.\n    ///\n    /// If the key name does not begin with the given prefix, the returned key will be\n    /// identical.\n    ///\n    /// Fails if the new key would be invalid, e.g. if the prefix is the entire key.\n    pub(super) fn strip_prefix<S>(&self, prefix: S) -> Result<Self>\n    where\n        S: AsRef<str>,\n    {\n        let prefix = prefix.as_ref();\n        ensure!(\n            prefix != self.name,\n            error::InvalidKeySnafu {\n                name: \"\",\n                msg: format!(\"strip_prefix of '{prefix}' matches key\")\n            }\n        );\n\n        let strip = prefix.to_string() + \".\";\n\n        // Check starts_with so we don't replace in the middle of the string...\n        let name = if self.name.starts_with(&strip) {\n            self.name.replacen(&strip, \"\", 1)\n        } else {\n            self.name.clone()\n        };\n\n        Self::new(KeyType::Data, name)\n    }","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/bottlerocket-os/bottlerocket/blob/0be31b34d2ff8a7558cd78b3a2e8035207f82597/sources/api/datastore/src/key.rs#L90-L126","documentation":"`strip_prefix` refuses to strip a prefix that equals the entire key name, because the result would be an empty (invalid) key. The resulting key is reported with an empty name ('') since no valid remainder exists.","triggerScenarios":"Calling key.strip_prefix(p) where p.to_string() == key.name() exactly — stripping the full key instead of a proper ancestor prefix.","commonSituations":"Prefix-based store listing code that iterates prefixes and accidentally includes the queried prefix itself as a key; computing relative keys where caller and callee use the same constant prefix.","solutions":["Check `prefix == key.name()` before calling strip_prefix and handle that case explicitly (e.g. return an empty/zero-length key)","Strip a strictly shorter prefix ending with the '.' separator","Change the loop to skip keys identical to the prefix"],"exampleFix":"// before\nlet child = key.strip_prefix(prefix)?; // fails when prefix == key\n// after\nlet child = if key.name() == prefix {\n    None\n} else {\n    Some(key.strip_prefix(prefix)?)\n};","handlingStrategy":"try-catch","validationCode":"if key.name() == prefix { /* handle identity */ }","typeGuard":null,"tryCatchPattern":"match key.strip_prefix(&prefix) { Err(e) if e.to_string().contains(\"matches key\") => None, o => Some(o?) }","preventionTips":["Check prefix != key name before stripping"],"tags":["datastore","key","prefix"],"backgroundTag":"invalid-argument-value","analyzedSha":"0be31b34d2ff8a7558cd78b3a2e8035207f82597","analyzedAt":"2026-09-10T14:35:41.363Z","contentChangedAt":"2026-09-10T14:35:41.363Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}