diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb
index acc9a10ea244e0e1f213efef86453c2b65f9ad6a..5954c031ebc2d68cafba025067a57cea8b604cac 100644
--- a/Library/Homebrew/cmd/gist-logs.rb
+++ b/Library/Homebrew/cmd/gist-logs.rb
@@ -37,12 +37,12 @@ module Homebrew
     if ARGV.include?("--new-issue") || ARGV.switch?("n")
       auth = :AUTH_TOKEN
 
-      unless GitHub.api_credentials
+      if GitHub.api_credentials_type == :none
         puts "You can create a personal access token: https://github.com/settings/tokens"
         puts "and then set HOMEBREW_GITHUB_API_TOKEN as authentication method."
         puts
 
-        auth = :AUTH_BASIC
+        auth = :AUTH_USER_LOGIN
       end
 
       url = new_issue(f.tap, "#{f.name} failed to build on #{MacOS.full_version}", url, auth)
@@ -118,9 +118,21 @@ module Homebrew
     headers = GitHub.api_headers
     headers["Content-Type"] = "application/json"
 
+    basic_auth_credentials = nil
+    if auth != :AUTH_USER_LOGIN
+      token, username = GitHub.api_credentials
+      case GitHub.api_credentials_type
+      when :keychain
+        basic_auth_credentials = [username, token]
+      when :environment
+        headers["Authorization"] = "token #{token}"
+      end
+    end
+
     request = Net::HTTP::Post.new(path, headers)
+    request.basic_auth(*basic_auth_credentials) if basic_auth_credentials
 
-    login(request) if auth == :AUTH_BASIC
+    login(request) if auth == :AUTH_USER_LOGIN
 
     request.body = Utils::JSON.dump(data)
     request
@@ -133,6 +145,7 @@ module Homebrew
     when Net::HTTPCreated
       Utils::JSON.load get_body(response)
     else
+      GitHub.api_credentials_error_message(response)
       raise "HTTP #{response.code} #{response.message} (expected 201)"
     end
   end
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 1fbb5afac5d3e5deecf50ff0fc74067a8af3c942..98ebcc9c8df8ec14996e6551105141d8963ba06c 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -484,7 +484,7 @@ module GitHub
   class RateLimitExceededError < Error
     def initialize(reset, error)
       super <<-EOS.undent
-        GitHub #{error}
+        GitHub API Error: #{error}
         Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token:
           #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset}
         and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
@@ -506,9 +506,12 @@ module GitHub
         EOS
       else
         message << <<-EOS.undent
-          The GitHub credentials in the OS X keychain are invalid.
+          The GitHub credentials in the OS X keychain may be invalid.
           Clear them with:
             printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase
+          Or create a personal access token:
+            #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset}
+          and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
         EOS
       end
       super message
@@ -536,32 +539,71 @@ module GitHub
     end
   end
 
-  def api_headers
-    @api_headers ||= begin
-        headers = {
-        "User-Agent" => HOMEBREW_USER_AGENT,
-        "Accept"     => "application/vnd.github.v3+json"
-      }
-      token, username = api_credentials
-      if token && !token.empty?
-        if username && !username.empty?
-          headers[:http_basic_authentication] = [username, token]
-        else
-          headers["Authorization"] = "token #{token}"
+  def api_credentials_type
+    token, username = api_credentials
+    if token && !token.empty?
+      if username && !username.empty?
+        :keychain
+      else
+        :environment
+      end
+    else
+      :none
+    end
+  end
+
+  def api_credentials_error_message(response_headers)
+    @api_credentials_error_message_printed ||= begin
+      unauthorized = (response_headers["status"] == "401 Unauthorized")
+      scopes = response_headers["x-accepted-oauth-scopes"].to_s.split(", ")
+      if !unauthorized && scopes.empty?
+        credentials_scopes = response_headers["x-oauth-scopes"].to_s.split(", ")
+
+        case GitHub.api_credentials_type
+        when :keychain
+          onoe <<-EOS.undent
+            Your OS X keychain GitHub credentials do not have sufficient scope!
+            Scopes they have: #{credentials_scopes}
+            Create a personal access token: https://github.com/settings/tokens
+            and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
+          EOS
+        when :environment
+          onoe <<-EOS.undent
+            Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope!
+            Scopes it has: #{credentials_scopes}
+            Create a new personal access token: https://github.com/settings/tokens
+            and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
+          EOS
         end
       end
-      headers
+      true
     end
   end
 
+  def api_headers
+    {
+      "User-Agent" => HOMEBREW_USER_AGENT,
+      "Accept"     => "application/vnd.github.v3+json"
+    }
+  end
+
   def open(url, &_block)
     # This is a no-op if the user is opting out of using the GitHub API.
     return if ENV["HOMEBREW_NO_GITHUB_API"]
 
     require "net/https"
 
+    headers = api_headers
+    token, username = api_credentials
+    case api_credentials_type
+    when :keychain
+      headers[:http_basic_authentication] = [username, token]
+    when :environment
+      headers["Authorization"] = "token #{token}"
+    end
+
     begin
-      Kernel.open(url, api_headers) { |f| yield Utils::JSON.load(f.read) }
+      Kernel.open(url, headers) { |f| yield Utils::JSON.load(f.read) }
     rescue OpenURI::HTTPError => e
       handle_api_error(e)
     rescue EOFError, SocketError, OpenSSL::SSL::SSLError => e
@@ -578,6 +620,8 @@ module GitHub
       raise RateLimitExceededError.new(reset, error)
     end
 
+    GitHub.api_credentials_error_message(e.io.meta)
+
     case e.io.status.first
     when "401", "403"
       raise AuthenticationFailedError.new(e.message)