{"record":{"id":"411de6a9edd18f42","repo":"GitoxideLabs/gitoxide","slug":"invalid-mode-change-can-t-flip-executable-bit-of","errorCode":null,"errorMessage":"invalid mode change: can't flip executable bit of {mode:?}","messagePattern":"invalid mode change: can't flip executable bit of (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-index/src/entry/mode.rs","lineNumber":135,"sourceCode":"pub enum Change {\n    /// The type of mode changed, like symlink => file.\n    Type {\n        /// The mode representing the new index type.\n        new_mode: Mode,\n    },\n    /// The executable permission of this file has changed.\n    ExecutableBit,\n}\n\nimpl Change {\n    /// Applies this change to `mode` and returns the changed one.\n    pub fn apply(self, mode: Mode) -> Mode {\n        match self {\n            Change::Type { new_mode } => new_mode,\n            Change::ExecutableBit => match mode {\n                Mode::FILE => Mode::FILE_EXECUTABLE,\n                Mode::FILE_EXECUTABLE => Mode::FILE,\n                _ => unreachable!(\"invalid mode change: can't flip executable bit of {mode:?}\"),\n            },\n        }\n    }\n}\n","sourceCodeStart":117,"sourceCodeEnd":140,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-index/src/entry/mode.rs#L117-L140","documentation":"`gix_index::entry::mode::Change::apply()` flips the executable bit of an index entry mode. The library panics because flipping the executable bit is only defined for regular files (`Mode::FILE` / `Mode::FILE_EXECUTABLE`); applying `Change::ExecutableBit` to a symlink, gitlink (submodule), or directory mode is an invalid mode change that the API cannot express.","triggerScenarios":"Constructing a diff/status change list that emits `Change::ExecutableBit` for a mode that is not `Mode::FILE` or `Mode::FILE_EXECUTABLE` and then calling `change.apply(mode)`. Typically a bug in code that computes `Change` values from tree-vs-index comparisons without classifying the entry type first.","commonSituations":"Writing custom index/diff logic that treats all entries uniformly and toggles the exec bit on submodule (`COMMIT`) or symlink (`SYMLINK`) entries; upstream changes where a submodule's mode changed; hand-built mode transitions applied to the wrong entry kind.","solutions":["Emit `Change::Type { new_mode }` instead of `Change::ExecutableBit` when the base mode is not a regular file.","Before calling `apply`, check `matches!(mode, Mode::FILE | Mode::FILE_EXECUTABLE)`; otherwise compute the target mode directly.","Fix the change-classification code so executable-bit changes are only derived from blob entries.","If you only need the resulting mode, skip `apply` entirely and construct the desired `Mode` literal."],"exampleFix":"// before\nlet new_mode = change.apply(mode); // panics for symlinks/gitlinks\n\n// after\nlet new_mode = match change {\n    Change::ExecutableBit if matches!(mode, Mode::FILE | Mode::FILE_EXECUTABLE) => change.apply(mode),\n    Change::ExecutableBit => mode, // exec bit meaningless for symlink/gitlink\n    Change::Type { new_mode } => new_mode,\n};","handlingStrategy":"validation","validationCode":"if !matches!(mode, Mode::FILE | Mode::FILE_EXECUTABLE) {\n    // ExecutableBit is undefined for symlinks/gitlinks; use a Type change instead.\n    return Err(anyhow::anyhow!(\"exec-bit change invalid for mode {mode:?}\"));\n}\nlet new_mode = change.apply(mode);","typeGuard":"fn exec_bit_applicable(mode: Mode) -> bool {\n    matches!(mode, Mode::FILE | Mode::FILE_EXECUTABLE)\n}","tryCatchPattern":"// This is a panic, not a caught error — avoid it via validation:\nlet new_mode = if exec_bit_applicable(mode) { change.apply(mode) } else { mode };","preventionTips":["Only emit `Change::ExecutableBit` for regular-file entries.","Use `Change::Type { new_mode }` for symlink, gitlink, or directory mode transitions.","Unit-test mode transitions against all `Mode` variants."],"tags":["panic","git","index","file-mode"],"backgroundTag":"invalid-state-transition","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}