ohmyzsh: command not found after starting zsh in AWS machines

$ zsh
complete:13: command not found: compdef

UPDATE: see solution at https://github.com/robbyrussell/oh-my-zsh/issues/4771#issuecomment-181122099

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 36 (18 by maintainers)

Most upvoted comments

TL;DR aws-cli will get updated someday, until then:

sudo chmod a-r /etc/profile.d/aws-cli.sh

Oh crap! You beat me to it. That’s exactly the problem. I’m reproducing the log at the end for future reference.

Explanation:

The aws_zsh_completer.sh file is a part of aws/aws-cli. Funnily enough, @blueyed (who has made significant contributions to Oh My Zsh, hence the fun part) contributed the commit that dropped the call to compinit because it broke completion: https://github.com/aws/aws-cli/commit/a2498c41b5bb7bbc189d3251081df1971597a510.

Now, the really offending file is /etc/profile.d/aws-cli.sh, because of sourcing the completion file without running compinit—or, at least, sourcing it in a point in time where compinit should’ve already been called. /etc/profile.d is soon enough in the initialization process that compinit hasn’t been run yet. See all the startup files for reference. Also, the aws_zsh_completer.sh file says explicitly enough that the file should be sourced in the zshrc file:

# Typically that would be called somewhere in your .zshrc.

I don’t know which package the aws-cli.sh file comes from, so I cannot submit a bug report; a quick google search only returns this file part of a Chef cookbook, which is correct because it runs compinit before, as well as a post in Japanese about this problem which suggests running compinit in a ~/.zshenv file to fix this problem.

Solutions:

The latter solution will not work in your case though, compinit will be running twice and, while you won’t see the error again, the aws cli completion won’t work. You could then source the aws_zsh_completer from within your zshrc file but that’s a horrible contraption that I particularly hate.

I think you can disable the loading of /etc/profile.d/aws-cli.sh by toggling off its readable attribute. Here’s the relevant part of the code that loads profile.d files:

        for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            . $i
        fi
        done

The [ -r $file ] code checks the readable attribute of $file. So with a simple chmod a-r /etc/profile.d/aws-cli.sh you should be all set.

Actionable items:

For everybody that posted here with this problem, you should make sure that you have the file /etc/profile.d/aws-cli.sh, or that at least you are using aws-cli in some way. If the former, you can already apply the chmod solution above.

If that’s not the case, post your diagnostic dump and we’ll figure it out.


Relevant part of the debug log. Notice the comment that says “make sure to run compinit before” 😂

+_src_etc_profile_d:11> . /etc/profile.d/aws-cli.sh
if [ -n "$ZSH_VERSION" ]; then
   source /usr/share/zsh/site-functions/aws_zsh_completer.sh
fi
+/etc/profile.d/aws-cli.sh:1> [ -n 5.0.2 ']'
+/etc/profile.d/aws-cli.sh:2> source /usr/share/zsh/site-functions/aws_zsh_completer.sh
# Source this file to activate auto completion for zsh using the bash
# compatibility helper.  Make sure to run `compinit` before, which should be
# given usually.
#
# % source /path/to/zsh_complete.sh
#
# Typically that would be called somewhere in your .zshrc.
#
# Note, the overwrite of _bash_complete() is to export COMP_LINE and COMP_POINT
# That is only required for zsh <= edab1d3dbe61da7efe5f1ac0e40444b2ec9b9570
#
# https://github.com/zsh-users/zsh/commit/edab1d3dbe61da7efe5f1ac0e40444b2ec9b9570
#
# zsh relases prior to that version do not export the required env variables!
#
# It is planned to write a proper zsh auto completion soon. Please talk
# to Frank Becker <fb@alien8.de>.

autoload -Uz bashcompinit
+/usr/share/zsh/site-functions/aws_zsh_completer.sh:19> autoload -Uz bashcompinit
bashcompinit -i
+/usr/share/zsh/site-functions/aws_zsh_completer.sh:20> bashcompinit -i
+bashcompinit:177> unfunction bashcompinit
+bashcompinit:178> autoload -Uz bashcompinit
+bashcompinit:179> return 0

_bash_complete() {
  local ret=1
  local -a suf matches
  local -x COMP_POINT COMP_CWORD
  local -a COMP_WORDS COMPREPLY BASH_VERSINFO
  local -x COMP_LINE="$words"
  local -A savejobstates savejobtexts

  (( COMP_POINT = 1 + ${#${(j. .)words[1,CURRENT]}} + $#QIPREFIX + $#IPREFIX + $#PREFIX ))
  (( COMP_CWORD = CURRENT - 1))
  COMP_WORDS=( $words )
  BASH_VERSINFO=( 2 05b 0 1 release )

  savejobstates=( ${(kv)jobstates} )
  savejobtexts=( ${(kv)jobtexts} )

  [[ ${argv[${argv[(I)nospace]:-0}-1]} = -o ]] && suf=( -S '' )

  matches=( ${(f)"$(compgen $@ -- ${words[CURRENT]})"} )

  if [[ -n $matches ]]; then
    if [[ ${argv[${argv[(I)filenames]:-0}-1]} = -o ]]; then
      compset -P '*/' && matches=( ${matches##*/} )
      compset -S '/*' && matches=( ${matches%%/*} )
      compadd -Q -f "${suf[@]}" -a matches && ret=0
    else
      compadd -Q "${suf[@]}" -a matches && ret=0
    fi
  fi

  if (( ret )); then
    if [[ ${argv[${argv[(I)default]:-0}-1]} = -o ]]; then
      _default "${suf[@]}" && ret=0
    elif [[ ${argv[${argv[(I)dirnames]:-0}-1]} = -o ]]; then
      _directories "${suf[@]}" && ret=0
    fi
  fi

  return ret
}

complete -C aws_completer aws
+/usr/share/zsh/site-functions/aws_zsh_completer.sh:63> complete -C aws_completer aws
+complete:1> emulate -L zsh
+complete:2> local args void cmd print remove
+complete:3> args=( -C aws_completer aws ) 
+complete:4> zparseopts -D -a void o: A: G: W: C: F: P: S: X: a b c d e f g j k u v 'p=print' 'r=remove'
+complete:6> [[ -n '' ]]
+complete:8> [[ -n '' ]]
+complete:13> compdef '_bash_complete -C aws_completer' aws
complete:13: command not found: compdef

👍 on the chmod a-r /etc/profile.d/aws-cli.sh trick. Every time I logged into my AWS box I got that error and I died a little inside. Now it’s gone and I want to give everyone a hug.

This is fixed as of aws-cli-1.11.83-1.46, pushed today.

I never considered that the printed error message was coming from my AWS box rather than from my local. chmoding the aws-cli.sh file did the trick. Thanks for the sleuthing!

Might be a corrupted compdump file. Try doing rm ~/*zcompdump* and restarting zsh.

This section (REDACTED) looks like it might be the problem, or at least part of it. It’s from /etc/profile.d/aws-cli.sh and /usr/share/zsh/site-functions/aws_zsh_completer.sh, which looks like a custom AWS client completion for zsh built on zsh’s bashcompinit portability layer, and redefining _bash_complete using its own logic. It calls bashcompinit, but does not call compinit. It is typically compinit which makes compdef and related functions available.

This could be that the AWS client stuff assumes that it will be called after something else has called compinit. When you’re running OMZ, it’s usually oh-my-zsh.sh which calls compinit. (In your case that’s being done [down here on line 567 of that log.) But since this AWS stuff is being sourced from /etc/profile.d, it’s run before your ~/.zshrc.

Looks like that AWS client stuff may need to be revised if it’s being run from /etc/profile.d ahead of the user’s initialization files. Specifically, it (or something preceding it in the load order) would need to call compinit. That may cause a problem with OMZ or normal ~/.zshrc files which also call compinit, because I think that resets the defined completions.