diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 35f26f7c1124663a118bc331e1fdd8ea76fd6a81..a3cb07172789f4f5d06476c4a60ce43ce27f2097 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -255,16 +255,19 @@ _bpftool_map_update_get_name()
 
 _bpftool()
 {
-    local cur prev words objword
+    local cur prev words objword json=0
     _init_completion || return
 
     # Deal with options
     if [[ ${words[cword]} == -* ]]; then
         local c='--version --json --pretty --bpffs --mapcompat --debug \
-	       --use-loader --base-btf'
+            --use-loader --base-btf'
         COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
         return 0
     fi
+    if _bpftool_search_list -j --json -p --pretty; then
+        json=1
+    fi
 
     # Deal with simplest keywords
     case $prev in
@@ -367,7 +370,7 @@ _bpftool()
                             ;;
                         *)
                             _bpftool_once_attr 'file'
-                            if _bpftool_search_list 'xlated'; then
+                            if _bpftool_search_list 'xlated' && [[ "$json" == 0 ]]; then
                                 COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \
                                     "$cur" ) )
                             else
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index d855118f0d9632a3f718260a45085339a74bde47..736defc6e5d0567ac02ae7572d8df823d9a7035b 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -849,9 +849,7 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
 		dd.finfo_rec_size = info->func_info_rec_size;
 		dd.prog_linfo = prog_linfo;
 
-		if (json_output && visual)
-			jsonw_null(json_wtr);
-		else if (json_output)
+		if (json_output)
 			dump_xlated_json(&dd, buf, member_len, opcodes, linum);
 		else if (visual)
 			dump_xlated_cfg(&dd, buf, member_len);
@@ -940,6 +938,10 @@ static int do_dump(int argc, char **argv)
 		usage();
 		goto exit_close;
 	}
+	if (json_output && visual) {
+		p_err("'visual' is not compatible with JSON output");
+		goto exit_close;
+	}
 
 	if (json_output && nb_fds > 1)
 		jsonw_start_array(json_wtr);	/* root array */