Skip to content

fzf tmux integration broken: mkfifo compatibility issue with uutils-coreutils #15

@Alrefai

Description

@Alrefai

Issue: fzf tmux integration broken with uutils-coreutils

Problem Description

fzf key bindings (Ctrl-T, Ctrl-R) stopped working in tmux sessions after adding uutils-coreutils-noprefix to home-manager configuration. The error manifested as:

mkfifo: invalid mode: invalid digit found in string
fzf-file-widget:zle:3: widgets can only be called when ZLE is active

Initial Investigation Path

1. Suspected tmux Configuration Issues

  • Hypothesis: tmux prefix key (C-s) was capturing key range
  • Investigation: Checked tmux key bindings and configuration
  • Result: ❌ Not the root cause - tmux config was correct

2. Suspected tmux 3.5a Breaking Changes

  • Hypothesis: Recent tmux version changes affected shell integration
  • Investigation: Found home-manager issue #5952 about tmux 3.5a shell handling changes
  • Result: ❌ Related but not the direct cause

3. Suspected fzf Shell Integration

  • Investigation:
    • Verified fzf functions were loaded (fzf-file-widget exists)
    • Confirmed key bindings were correct ("^T" fzf-file-widget)
    • Tested ZLE status (was active: $options[zle] = on)
  • Result: ❌ Shell integration was working correctly

4. Environment Comparison Testing

  • Method: Tested fzf behavior inside vs outside tmux
  • Discovery: Same mkfifo error occurred in both environments
  • Key insight: Issue wasn't tmux-specific

Root Cause Discovery

The Breakthrough

During testing, user mentioned recently adding:

uutils-coreutils-noprefix # Rust rewrite of the GNU coreutils

Confirmation Test

Commenting out uutils-coreutils-noprefix immediately fixed the issue, confirming the root cause.

Technical Analysis

The issue occurred because:

  1. GNU vs Rust syntax differences: fzf shell integration uses mkfifo -m o+w (GNU syntax)
  2. uutils-coreutils incompatibility: The Rust implementation expects octal modes like -m 622
  3. Argument parsing failure: mkfifo -m o+w caused "invalid mode" error in uutils implementation

Solutions Explored

Solution 1: Remove Problematic Package ✅ (Temporary)

# uutils-coreutils-noprefix # Commented out
  • Pros: Immediate fix
  • Cons: Lose performance benefits of Rust coreutils

Solution 2: Remove Only mkfifo ✅ (Simple)

uutils-coreutils-no-mkfifo = pkgs.uutils-coreutils-noprefix.overrideAttrs (oldAttrs: {
  postInstall = (oldAttrs.postInstall or "") + ''
    rm -f $out/bin/mkfifo  # Let system use GNU version
  '';
});
  • Pros: Keep Rust performance for other tools, simple implementation
  • Cons: Lose Rust implementation for mkfifo entirely

Solution 3: GNU Compatibility Wrapper ✅ (Elegant)

uutils-coreutils-fzf-compat = pkgs.uutils-coreutils-noprefix.overrideAttrs (oldAttrs: {
  postInstall = (oldAttrs.postInstall or "") + ''
    # Create GNU-compatible wrapper for mkfifo
    mv $out/bin/mkfifo $out/bin/.mkfifo-uutils
    
    cat > $out/bin/mkfifo << 'EOF'
#!/usr/bin/env bash
set -euo pipefail

# Find the actual uutils coreutils multicall binary
uutils_coreutils="$(dirname "$(readlink -f "$0")")/.mkfifo-uutils"

# Handle GNU coreutils compatibility for fzf
if [[ $# -ge 2 && "$1" == "-m" && "$2" == "o+w" ]]; then
  # Convert GNU syntax to octal: o+w = 622 (owner rw, group w, other w)
  shift 2
  exec "$uutils_coreutils" mkfifo -m 622 "$@"
else
  # Pass through all other arguments unchanged
  exec "$uutils_coreutils" mkfifo "$@"
fi
EOF
    chmod +x $out/bin/mkfifo
  '';
});

Key Technical Insights

uutils-coreutils Architecture

  • Uses multicall binary approach (single coreutils executable)
  • Determines tool behavior via symlink name or explicit subcommand
  • When calling directly: coreutils mkfifo -m 622 file (not just coreutils -m 622 file)

Wrapper Design Patterns

  1. Hidden file pattern: mv mkfifo .mkfifo-uutils (dot prefix hides implementation detail)
  2. Runtime path resolution: $(dirname "$(readlink -f "$0")") for build-time → runtime compatibility
  3. Transparent compatibility: Wrapper intercepts specific GNU syntax while passing through everything else

Permission Translation

  • GNU syntax: -m o+w (symbolic: owner+group+other write)
  • Octal equivalent: -m 622 (owner: rw-, group: -w-, other: -w-)

Debugging Methodology Learnings

  1. Start with recent changes: "What changed recently?" led to the breakthrough
  2. Environment isolation: Testing inside/outside tmux helped rule out tmux-specific issues
  3. Incremental hypothesis testing: Systematically ruled out configuration, version, and integration issues
  4. Binary inspection: Understanding the multicall binary architecture was crucial for the final solution

Impact & Resolution

  • Root cause: Package compatibility issue, not configuration problem
  • Final solution: Elegant wrapper maintaining Rust performance with GNU compatibility
  • Broader lesson: Alternative coreutils implementations can have subtle compatibility differences

This issue demonstrates the importance of compatibility layers when adopting modern tool replacements in complex environments.

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