And again, I remind you that $active might not even be a channel if you lag from the server THEY are on. You might have switched to a query window or your Status window. In such a case, your 317 WILL fail because $active is not a channel, and you definitely are not opped in your Status window. You also have to remember to never user your /kidle alias unless you are opped or it will fail as well. Everything will be fine if you keep the channel you triggered the /kidle alias as the active window until all the whois results are back from the servers. Of course, in a large channel, you will flood yourself off if you don't SendQ off first. You have not taken server<-->server lag into account at all, but presumably you don't care.

$active is not the same thing as $chan (which doesn't matter anyway because 317 does not have a $chan associated with it).

There is no need to use /PRIVMSG when /MSG will do the same thing and allow mIRC to update your $active window properly. /PRIVMSG does not echo your text into that $active, /MSG does. When you want to look for someone's idle time, you have to ask the server they are on; most IRCds that I know of do not propagate idle times across servers, so you have to /WHOIS nick nick As for your loop, here is a much cleaner way:
Code:

  var %i = 1
  ;  Moving to the next non-op (will kick everyone who is not opped if they are idle too long)
  while ($nick(#,%i,a,o)) {
    whois $ifmatch $ifmatch
    inc %i
  }