19

With version 75 of Chrome just released, our tests no longer run properly. They give the stacktrace pasted below. We are using ruby on rails v. 5.1.6.2 with rspec, selenium-webdriver 3.8.0.

Stacktrace:

Selenium::WebDriver::Error::UnknownCommandError:
            unknown command: Cannot call non W3C standard command while in W3C mode
          # 0   chromedriver                        0x000000010c46e8e9 chromedriver + 3594473
          # 1   chromedriver                        0x000000010c3fe543 chromedriver + 3134787
          # 2   chromedriver                        0x000000010c1aa29f chromedriver + 692895
          # 3   chromedriver                        0x000000010c11a691 chromedriver + 104081
          # 4   chromedriver                        0x000000010c11b7d5 chromedriver + 108501
          # 5   chromedriver                        0x000000010c42d555 chromedriver + 3327317
          # 6   chromedriver                        0x000000010c438e60 chromedriver + 3374688
          # 7   chromedriver                        0x000000010c438bf8 chromedriver + 3374072
          # 8   chromedriver                        0x000000010c40cd39 chromedriver + 3194169
          # 9   chromedriver                        0x000000010c4396d8 chromedriver + 3376856
          # 10  chromedriver                        0x000000010c420f27 chromedriver + 3276583
          # 11  chromedriver                        0x000000010c456064 chromedriver + 3493988
          # 12  chromedriver                        0x000000010c474617 chromedriver + 3618327
          # 13  libsystem_pthread.dylib             0x00007fff7744c2eb _pthread_body + 126
          # 14  libsystem_pthread.dylib             0x00007fff7744f249 _pthread_start + 66
          # 15  libsystem_pthread.dylib             0x00007fff7744b40d thread_start + 13
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/response.rb:32:in `initialize'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/common.rb:81:in `new'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/common.rb:81:in `create_response'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/default.rb:104:in `request'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/bridge.rb:166:in `execute'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/oss/bridge.rb:579:in `execute'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/oss/bridge.rb:526:in `element_displayed?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/common/element.rb:199:in `displayed?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/selenium/node.rb:148:in `visible?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/node/element.rb:269:in `block in visible?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/node/base.rb:81:in `synchronize'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/node/element.rb:269:in `visible?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/queries/selector_query.rb:84:in `matches_filters?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/result.rb:29:in `block in initialize'

Our driver configuration:

File.write(LOG_FILE_PATH, '')
Selenium::WebDriver.logger.level = :debug
Selenium::WebDriver.logger.output = LOG_FILE_PATH
Capybara.register_driver :selenium do |app|
  # from https://github.com/SeleniumHQ/selenium/issues/3738
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: {browser: 'ALL'})
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument '--disable-infobars' # hide info bar about chrome automating test
  # if we don't use this flag, every selenium test will die with the error:
  # "unknown error: Chrome failed to start: exited abnormally"
  options.add_argument '--no-sandbox'
  options.add_argument '--headless' if ENV.fetch("HEADLESS", nil).present?
  options.add_argument '--window-size=1600,2400'
  options.add_argument '-–allow-file-access-from-files' # TODO Julie - may help with file specs?
  options.add_preference('homepage', 'about:blank') # TODO is this working?
  options.add_preference('profile.default_content_settings.popups', 0)
  options.add_preference('download.default_directory', DownloadHelpers::PATH.to_s)
  Capybara::Selenium::Driver.new(
    app,
    clear_local_storage: true,
    clear_session_storage: true,
    browser: :chrome,
    options: options,
    desired_capabilities: capabilities,
  )
end

UPDATE:

I was able to get our tests to work temporarily using capabilities = { "chromeOptions" => {'w3c' => false} }.

After updating chromedriver, we began receiving the error "unknown error: DevToolsActivePort file doesn't exist". In order to fix this problem, we upgraded our selenium-webdriver gem to 3.142.3 and this fixed the issue, allowing us to use w3c without any additional parameters.

Julie
  • 1,941
  • 3
  • 17
  • 30

8 Answers8

24

First the solution

As promised by John Chen [Owner - WebDriver for Google Chrome] yesterday, new versions of ChromeDriver 75.0.3770.90 and 76.0.3809.25 have been released, and are now available at the ChromeDriver Downloads site. These versions include the following bug fixes over the previous releases of ChromeDriver 75 and 76:

  • Fixed a bug that incorrectly rejected POST requests with empty body in OSS mode
  • Added new endpoints for retrieving Chrome log

In addition, version 76.0.3809.25 also includes the following change:

  • Added endpoint for Is Displayed command in W3C mode

Email Snapshot

75_76


Details

It will be against the best practices to turn off w3c in chromedriver to address the error:

Selenium::WebDriver::Error::UnknownCommandError:
        unknown command: Cannot call non W3C standard command while in W3C mode

as the current implementation of ChromeDriver requests a W3C-compliant session to the client.


However, this error message implies that the ChromeDriver was unable to invoke a non W3C standard command while in W3C mode while initiating/spawning a new WebBrowser i.e. Chrome Browser session.

The main issue is, when ChromeDriver's client requests a W3C-compliant session, the response from ChromeDriver does not conform to the W3C spec, and causes errors in language APIs.

As per the discussion in ChromeDriver response in W3C mode is not standard compliant John Chen (Owner - WebDriver for Google Chrome) mentioned Simon Stewart (Creator - WebDriver) have updated that:

  • The new session response for a w3c session should look like:

    {
      "value": {
        "sessionId": "some-uuid",
        "capabilities": {
          "browserName": "chrome",
          ...
        }
      }
    }
    
  • But when starting a new session with the w3c option set to true in the chromeOptions, the returned response looked like:

        {
          "sessionId": "af4656c27fb94485b7872e1fc616923a",
          "status": "ok",
          "value": {
            "browserName": "chrome",
            ...
          }
        }
    

Which is neither a correctly formed response for the JSON Wire Protocol (where "status" would be an integer), nor a correctly formed W3C response and without a correctly formed response, the w3c compatible cannot be used.

This revision and this commit addressed this issue.


This usecase

Presumably you are using ChromeDriver v75.x with Chrome v75.x and in case you are still seeing the error, you need to pass the ExperimentalOption w3c as true explicitly as follows:

  • Ruby code sample:

    capabilities = { "chromeOptions" => {'w3c' => true} }
    
  • Java code sample:

    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    
    public class W3c {
      public static void main(String[] args) throws Exception {
        ChromeOptions opt = new ChromeOptions();
        opt.setExperimentalOption("w3c", true);
        ChromeDriver driver = new ChromeDriver(opt);
        driver.get("https://www.google.co.in");
      }
    }
    
  • Python code sample:

    from selenium import webdriver
    
    opt = webdriver.ChromeOptions()
    opt.add_experimental_option('w3c', True)
    driver = webdriver.Chrome(chrome_options=opt)
    driver.get('https://www.google.co.in')
    

Update

Till ChromeDriver v74.x, Chrome and ChromeDriver combo was running in w3c mode by default but there was bug with in the chromedriver/server/http_handler.cc. As per the details in goog:chromeOptions.w3c=false doesn't work for POST request with empty body:

Method HttpHandler::HandleCommand checks the value of the kW3CDefault constant instead of session goog:chromeOptions.w3c value. As a result, JSON Wire protocol support was broken, where POST requests with an empty body are allowed. JSON Wire protocol will be in demand until displayed endpoint is resumed in the w3c mode. It should be noted that W3C WebDriver specification doesn't forbid the use of 'displayed' endpoint and this feature is actively used in some APIs.

As Is Element Displayed command is not part of W3C spec, but is still used by some APIs, and its functionality can be difficult to replicate in those APIs. This Change List [revision and commit] re-enables this command in W3C mode to ease transition to W3C mode.

@John have already confirmed us to expect an update to ChromeDriver v75.0 tomorrow with the fix.

danronmoon
  • 3,814
  • 5
  • 34
  • 56
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    FYI it seems python selenium 3.141 works without needing `opt.add_experimental_option('w3c', True)` For extra fun, selenium people just changed the image tagged 3.141.59, which used to deploy chrome 72: now it deploys chrome 75, so I can see the error exploding in a lot of people's face https://hub.docker.com/r/selenium/node-chrome/tags – piro Jun 05 '19 at 13:05
  • 1
    @DebanjanB, passing a value of `true` does not avoid this error when running Ruby selenium-webdriver with latest Chrome v75.x and Chromedriver v75.x Passing a value of `false` does avoid the error, but as you say isn't a best practice. The referenced discussion and commit was from back in 2017, apparently something else has recently changed as is causing this to fail. Any idea how to get this working with an explicit value of `true`? – PinnyM Jun 13 '19 at 05:18
  • 1
    @DebanjanB thanks for the research! I updated your answer to summarize your findings, please adjust as you feel necessary. – PinnyM Jun 13 '19 at 13:02
  • @DebanjanB - I've downloaded the new 75.0.3770.90 version and still am getting a NotImplementException when calling ReadOnlyCollection.IndexOf. I don't suppose you have a C# example of disabling W3C compliance? I found chromeOptions.UseSpecCompliantProtocol, but that hasn't resolved the issue for me. – Tyler Nielsen Jun 14 '19 at 14:08
  • @TylerNielsen Can you try out **76.0.3809.25** once as it contains the fix for `Is Displayed` issue? – undetected Selenium Jun 14 '19 at 14:11
  • 3
    @DebanjanB I can confirm that 76.0.3809.25 works just fine. Unfortunately, 75.0.3770.90 does not and 76 is still in beta. Any hope of getting this fix merged into the stable branch? – PinnyM Jun 16 '19 at 05:16
  • @TylerNielsen I think you should be able to use `chromeOptions.AddAdditionalCapability("w3c", true)` (or `false` as the need may be) – PinnyM Jun 16 '19 at 16:38
  • @PinnyM Thanks for the update. I understand _Chrome 75.x_ is in beta but for _Chrome/ChromeDriver v75.0_ we need the stacktrace to understand what's going wrong. – undetected Selenium Jun 17 '19 at 07:04
  • @DebanjanB The error and stacktrace is identical to what the OP posted. – PinnyM Jun 17 '19 at 18:05
  • This should have been dup'd to your answer on https://stackoverflow.com/questions/56111529/cannot-call-non-w3c-standard-command-while-in-w3c-mode-seleniumwebdrivererr. Why would you post all of this twice? – JeffC Jun 19 '19 at 21:54
9

For the Javascript people (I specifically use WebdriverIO) make sure you use 'goog:chromeOptions'

  capabilities: {
    browserName: 'chrome',
    'goog:chromeOptions': {
        'w3c': false
    }
  }

Else you'll get

unknown error: Illegal key values seen in w3c capabilities: [chromeOptions]
bonjonbovi
  • 121
  • 2
  • 2
    Using selenium-webdriver 4.0.0-alpha.4 and chromedriver 76.0.1 this worked for me: `const driver = new Builder().withCapabilities({ browserName: 'chrome', chromeOptions: { w3c: false } })...build();` – Milanka Sep 10 '19 at 11:38
  • That worked like a charm. I was trying to integrate my Protarctor suite with Jenkins to run on ECS environment using Selenium Grid. Up-voted. – Harisha K P Jan 31 '20 at 13:53
7

After doing options = Selenium::WebDriver::Chrome::Options.new you can do options.add_option('w3c', false)

4

I'm facing the same issue.

I tried to disable using capabilities = Selenium::WebDriver::Remote::Capabilities.chrome({ "chromeOptions" => {'w3c' => false} }) but it didn't work.

Then I changed to capabilities = { "chromeOptions" => {'w3c' => false} } and now it works.

Maybe it can help you.

1

This is how it can be done in Behat with Mink: #behat #mink

  Behat\MinkExtension:
    base_url: "your_site_url"
    browser_name: 'chrome'
    goutte: ~
    javascript_session: selenium2
    selenium2:
      wd_host: http://127.0.0.1:4444/wd/hub
      capabilities:
        browser: chrome
        extra_capabilities:
          chromeOptions:
            args: ['--headless', '--disable-gpu']
            w3c: false
0

PHP Behat-Mink-Selenium users see this post for information: https://medium.com/@alex.designworks/chromedriver-75-enforces-w3c-standard-breaking-behat-tests-460cad435545 and GitHub issue https://github.com/minkphp/MinkSelenium2Driver/issues/293

As of this post, the "workaround" is to fall back to Chrome 74 for those using Behat-Mink-Selenium.

Phil Davis
  • 303
  • 1
  • 3
  • 9
0
{ 
  'platformName':'Android', 
  'platformVersion':'8.0.0',
  'deviceName':'Samsung Galaxy S9',
  'deviceType':'Phone', 
  'nativeWebTap': 'True',
  'browser' : 'Chrome',
  "goog:chromeOptions": {'w3c': False}
}

use goog:chromeOptions options to set w3c True or False. on console you will see the same getting passed.

user8672807
  • 124
  • 5
-1

I recently upgraded appium to 1.18 , using chromeDriver version 84 and my chrome browser version is also 84. I use appium python library to start a browser. My capabilities are like below but I get error -"WebDriverException: Message: 'chromeOptions' must be of type object". Please let me know whats wrong with my capabilities.

{ 
  'platformName':'Android', 
  'platformVersion':'8.0.0',
  'deviceName':'Samsung Galaxy S9',
  'deviceType':'Phone', 
  'nativeWebTap': 'True',
  'browser' : 'Chrome',
  'chromeOptions' : '{args: [ 'w3c : false']}' 
}
For Testing
  • 281
  • 2
  • 5
  • 19