Bad array subscript error when trying to increment an associative array element

The single quote in key name is causing the parser to treat it as a un-terminated quote character. One way to fix this would be to escape the ' character in the key

key="john's"
printf -v escKey "%q" "$key"

now because of the %q specifier, printf() would have applied required escapes to all shell meta characters i.e. making it "shell-quoted" and re-usable. If you print the contents of escKey you'll notice the ' escaped

printf '%s\n' "$escKey"
john\'s

Now you can use this keyname in your associative array. Remember you can always manually add the escapes which could be messy. Since %q is a native way provided by the shell, it is much safe to use it.

(( dict["$escKey"]++ ))

Also in bash versions >= 4.4 parameter expansion has @Q which is a shortcut for %q specifier of printf() using which you can do

(( dict["${key@Q}"]++ ))

You need to make sure, by escaping $, that $var isn't expanded until Bash starts parsing dict[$var]++ as an arithmetic expression.

$ (( dict[\$var]++ ))
$ declare -p dict
declare -A dict=(["john's"]="2" )

On newer versions of Bash, enabling the assoc_expand_once shell option works too, but this is unsafe when keys are read from an untrusted source. An example of how even when this option is enabled the shell can still be tricked into executing arbitrary commands with a tainted $var is given in Stephane's answer.