Mendiagnosis masalah fzf yang paling sering terjadi di lapangan: membaca log internal dengan --debug dan FZF_LOG_LEVEL, warna yang tidak tampil karena pengaturan terminal, preview yang error, sampai exit code yang membingungkan. Termasuk integrasi shell yang gagal dimuat, konflik keybinding, dan rendering yang rusak di tmux dan Zellij beserta solusinya.

Di episode 17 kalian mengoptimalkan fzf untuk dataset besar — memilih algoritma, membatasi item, dan meringankan preview. Semua teknik itu berasumsi fzf berjalan normal. Tetapi di lapangan, ada kalanya fzf berperilaku aneh: warna tidak muncul, preview diam, keybinding tidak merespons, atau fzf langsung keluar dengan exit code yang tidak jelas. Episode 18 ini adalah babak troubleshooting & debugging — membekali kalian metode untuk mendiagnosis, bukan sekadar daftar trik.
Bayangkan fzf sebagai mesin yang sehat: ketika gejalanya muncul — bunyi aneh, asap tipis, atau mesin mati mendadak — kalian tidak langsung mengganti seluruh mesin. Kalian mulai dari indikator yang tersedia: log, lampu peringatan, dan test sederhana. Prinsip yang sama berlaku di sini: mulai dari data yang paling bisa dipercaya (log dan exit code), lalu menyempit ke kemungkinan.
Episode ini membahas lima wilayah diagnosis: log internal fzf, masalah warna dan $TERM, preview yang error, exit code yang "aneh", integrasi shell yang tidak termuat, konflik keybinding dengan shell dan tmux, serta rendering di tmux dan Zellij.
--debug dan FZF_LOG_LEVELKapan terakhir kali kalian ingin fzf "menceritakan" apa yang sedang terjadi? Fzf tidak banyak bicara — sampai kalian memintanya. Untuk itulah ada log internal: opsi --debug menyalakan mode debug yang menuliskan log ke file /tmp/fzf-debug.log — catatan peristiwa seperti input yang diterima, event yang dipicu, dan kesalahan internal.
Verbosity log dikendalikan lewat environment variable FZF_LOG_LEVEL: dari yang paling tenang (error) sampai yang paling ramai (debug). Lokasi file bisa kalian pindahkan dengan FZF_LOG_FILE — berguna bila /tmp dibersihkan atau kalian ingin menyimpan log di direktori proyek:
export FZF_LOG_LEVEL=debug
export FZF_LOG_FILE="$HOME/fzf-debug.log"
fzfTip
Debug mode adalah pemeriksaan pertama ketika gejala sulit dijelaskan — prompt tidak muncul, reload tidak berjalan, atau daftar tidak ter-update. Log sering menampilkan penyebab yang tidak terlihat di layar. Ingat untuk mengembalikan FZF_LOG_LEVEL ke nilai tenang setelah selesai, karena debug menulis banyak baris setiap kali fzf berjalan.
$TERM dan Terminal KalianGejala paling umum kedua: fzf berjalan, tetapi hanya hitam putih — tidak ada warna, tidak ada highlight. Ini hampir selalu tentang bagaimana terminal mengiklankan kemampuannya. Dua variabel yang menentukan:
$TERM — mengiklankan kemampuan terminal (berapa warna, mendukung tidaknya kontrol tertentu). Nilai dumb atau xterm membuat fzf menahan fitur rendering.$COLORTERM — menandai dukungan True Color (24-bit); nilai truecolor adalah sinyal untuk fzf dan bat agar berani memakai warna penuh.echo "$TERM"
echo "$COLORTERM"Di dalam tmux, $TERM sering turun menjadi screen atau xterm — keduanya membatasi jumlah warna. Perbaikan standar: arahkan tmux memakai tmux-256color dan teruskan True Color ke aplikasi di dalamnya:
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",*:Tc"Note
Ada satu penjegal halus: environment variable NO_COLOR (dan variabel no-color) mematikan warna di banyak aplikasi — termasuk fzf. Jika warna hilang di semua tempat sekaligus, cek echo $NO_COLOR dulu; sering kali nilainya tersetel di suatu dotfile dan melenyapkan warna dari seluruh ekosistem tanpa bunyi apa pun.
Preview adalah bagian yang paling sering "bermasalah" — dan hampir selalu bukan salah fzf, melainkan perintah preview itu sendiri. Ingat model mental dari episode 10: setiap kali kursor berpindah, fzf menjalankan ulang perintah preview dengan item baru sebagai {}. Jika perintahnya error, fzf hanya menampilkan area kosong atau teks error yang lewat cepat.
Tiga pemeriksaan yang menyelesaikan hampir semua kasus:
{} dengan satu item nyata dan jalankan di shell. Jika error muncul di sana, fzf tidak akan bisa menyembunyikannya.rg yang tidak menemukan apa pun keluar dengan kode 1, dan fzf menganggapnya "gagal" — preview tampak diam. Akhiri dengan || true untuk menetralkan.bat, delta, atau jq yang belum terpasang membuat preview tampak kosong padahal seharusnya menampilkan isi file.fzf --preview 'rg -n {q} {} || true'
fzf --preview 'bat --color=always --style=plain {} 2>/dev/null'Important
Satu detail yang mengecoh banyak orang (kita bahas di episode 14): fzf hanya menampilkan pesan error dari FZF_DEFAULT_COMMAND jika perintah itu tidak menghasilkan output sama sekali. Jika perintah menghasilkan sebagian output lalu gagal, fzf menganggapnya sukses dan tidak menampilkan apa pun. Untuk diagnosis, jalankan perintah sumber secara terpisah dan periksa exit code-nya dengan echo $? — bukan mengandalkan pesan dari fzf.
Ketika fzf keluar sendiri dan script kalian gagal di langkah berikutnya, exit code adalah saksi utama. Exit code fzf sudah terdokumentasi dan deterministik:
| Exit Code | Arti | Kemungkinan Penyebab |
|---|---|---|
0 | Keluar normal | Item dipilih atau tombol --expect ditekan |
1 | Tidak ada pilihan | Daftar kosong, atau pengguna membatalkan tanpa pilihan |
2 | Error | Kesalahan penggunaan opsi atau keadaan internal |
126 | Izin ditolak | Perintah pada aksi become tidak dapat dieksekusi |
127 | Perintah tidak ditemukan | Shell command pada aksi become tidak valid |
130 | Diinterupsi | Ctrl-C atau Esc ditekan |
Kode seperti 127 dan 126 hampir selalu datang dari aksi become di episode 15 — bukan dari fzf itu sendiri, melainkan dari perintah yang ingin fzf jalankan. Script kalian seharusnya menangkap kode-kode ini secara eksplisit, misalnya case "$?" in 0) ... ;; 1) ... ;; 130) ... ;; esac, supaya kegagalan tidak tersamar sebagai keberhasilan kosong.
Gejala klasik: Ctrl+T, Ctrl+R, dan Alt+C tidak melakukan apa-apa, padahal fzf sudah terpasang. Ini berarti keybinding shell tidak pernah terpasang — bukan masalah fzf-nya. Cara pemasangan integrasi berbeda per shell:
eval "$(fzf --zsh)"
eval "$(fzf --bash)"fzf --fish | sourceKesalahan yang paling sering menjatuhkan orang:
eval "$(fzf --bash)" tidak berfungsi di zsh dan sebaliknya.~/.bash_profile untuk sesi login; integrasi yang hanya ada di ~/.bashrc tidak aktif sampai shell interaktif baru dibuka — dan sebaliknya. Biasakan: integrasi fzf di ~/.bashrc, ~/.zshrc, atau config.fish, lalu buka terminal baru alih-alih hanya source file.$PATH saat eval dijalankan. Jika $(fzf --zsh) dieksekusi sebelum direktori instalasi fzf masuk ke $PATH, eval menghasilkan string kosong.Cara verifikasi tercepat: type fzf-history-widget di zsh — jika memunculkan fungsi, integrasi sudah terpasang; jika "not found", integrasi belum dimuat.
Warning
Jangan meletakkan pemanggilan integrasi dua kali (misalnya sekali di plugin manager dan sekali manual di ~/.zshrc). Binding ganda tidak membahayakan, tetapi membuat konfigurasi sulit didiagnosis: kalian tidak pernah yakin versi mana yang aktif. Satu sumber, satu pemanggilan — itulah aturan untuk integrasi shell yang bisa di-debug.
Integrasi sudah termuat, tetapi tombol tetap tidak merespons — atau merespons sesuatu yang lain. Ini adalah konflik keybinding: tombol yang sama sudah dipakai oleh lapisan lain. Dua kasus yang paling umum:
Di zsh, widget Ctrl+R milik fzf bisa digeser oleh plugin seperti zsh-autosuggestions yang ikut memakai Ctrl+R. Dalam zsh, binding yang terakhir dipanggil menang — jadi panggil ulang binding fzf setelah plugin lain dimuat:
bindkey '^R' fzf-history-widgetDi tmux, prefix Ctrl+B dipegang lebih dulu oleh tmux sebelum diteruskan ke aplikasi di dalamnya. Tombol Ctrl+B bawaan fzf (berpindah kata) tidak akan pernah sampai ke fzf selama ada di dalam tmux. Solusinya: ganti tombol fzf dengan --bind, bukan melawan prefix tmux:
fzf --bind 'alt-b:backward-word,alt-f:forward-word'Tip
Untuk konflik dengan tmux secara umum, dua opsi: mengubah prefix tmux (misalnya Ctrl+A), atau memindahkan fzf ke popup dengan --popup — dalam popup, ketukan tombol masih diteruskan ke fzf, tetapi area interaksinya lebih terisolasi dari keymap pane lain. Pilih sesuai kenyamanan; tidak ada jawaban tunggal yang benar.
Kategori terakhir: fzf berjalan, tetapi tampilannya rusak — border terpotong, karakter hantu, atau warna terbalik. Ini hampir selalu masalah rendering pada terminal multiplexer, bukan bug fzf.
Border popup. Di episode 12 kita membahas --popup dan --border. Jika kalian berada di tmux 3.7+ atau Zellij, --popup memakai border native — dan jika kalian menyebut --border secara eksplisit, fzf berganti menggambar border sendiri. Ketika border tampak aneh atau dobel, periksa apakah kalian mencampur keduanya secara tidak sengaja.
Ghost characters di Zellij. Gejala khas: sisa karakter atau warna yang salah posisi di dalam Zellij. Ini masalah lama yang dipicu cara fzf menggerakkan kursor horizontal. Sejak fzf 0.74.1, fzf memakai CHA (Cursor Horizontal Absolute) alih-alih kombinasi CR + CUF untuk gerakan horizontal — dan perbaikan ini menghilangkan ghost characters di Zellij. Jika kalian mengalaminya, upgrade fzf ke 0.74.1 atau lebih baru lebih efektif daripada mengutak-atik tema.
Layar kacau setelah keluar. Terkadang setelah fzf selesai, layar terminal terlihat berantakan — sisa border atau prompt ganda. Perintah reset (atau tput reset) memulihkan terminal ke keadaan bersih. Ini bukan tanda kerusakan permanen; hanya terminal yang kehilangan sinkronisasi status.
resetCaution
Aturan diagnostik yang berlaku untuk semua kategori: ubah satu variabel pada satu waktu. Jangan sekaligus mengganti $TERM, FZF_DEFAULT_OPTS, dan versi fzf — kalian tidak akan pernah tahu mana yang menyembuhkan. Reproduksi masalah dengan perintah fzf sekecil mungkin (seq 100 | fzf), lalu tambahkan kompleksitas pelan-pelan.
| Kesalahan | Gejala | Solusi |
|---|---|---|
Log di error level | Tidak ada jejak saat fzf aneh | Set FZF_LOG_LEVEL=debug dan baca /tmp/fzf-debug.log |
$TERM bernilai dumb atau xterm | Warna tidak tampil | Gunakan terminal dengan TERM yang mendukung 256 warna |
| Di tmux warna pucat | Warna terbatas 16 | default-terminal "tmux-256color" + terminal-overrides ",*:Tc" |
| Preview diam | Perintah preview error atau keluar kode 1 | Jalankan manual, tambahkan || true, cek command -v |
| Exit code 127/126 | Perintah become tidak ditemukan/ditolak | Perbaiki perintah pada aksi become, bukan fzf |
Ctrl+T tidak berfungsi | Integrasi shell tidak dimuat | eval "$(fzf --zsh)" di file yang benar, buka shell baru |
Ctrl+R membuka hal lain | Konflik dengan plugin lain | Panggil bindkey '^R' fzf-history-widget paling akhir |
| Ghost characters di Zellij | Sisa karakter saat bergerak | Upgrade fzf ke 0.74.1+ (fix CHA) |
Pada episode 18 ini kalian membangun kemampuan diagnostik: membaca log internal dengan --debug dan FZF_LOG_LEVEL; memeriksa $TERM dan $COLORTERM saat warna tidak muncul; menguji perintah preview secara manual dan menetralkan exit code-nya; memahami arti setiap exit code fzf dari 0 sampai 130; memastikan integrasi shell dimuat dengan eval yang benar di file yang benar; menyelesaikan konflik keybinding dengan zsh dan tmux; serta memperbaiki rendering di tmux dan Zellij — termasuk perbaikan CHA di fzf 0.74.1.
Pesan yang harus dibawa pulang: gejala fzf yang "rusak" hampir selalu berasal dari lingkungan di sekelilingnya — terminal, shell, atau multiplexer — bukan dari fzf itu sendiri. Diagnosis yang baik berjalan dari yang paling bisa dipercaya (log dan exit code) menuju yang paling mungkin (lingkungan).
Dan karena troubleshooting sering kali berakhir dengan "upgrade fzf ke versi terbaru", episode berikutnya menjadi sangat relevan. Di episode 19 kita membahas fitur stabil terbaru (0.70 - 0.74): --popup yang matang di tmux dan Zellij, --listen yang semakin stabil, --gutter dan --highlight-line, synchronized update mode untuk mengurangi kedipan, hingga distribusi modern dengan paket .deb dan binary multi-platform.