I spent hours trying to solve this bug and the solution was so simple. 
My rpcpassword in my bitcoin.conf file contained a '#' character.

Prevent this from happening, by outputting this an error or warning when users run bitcoind.

Right now, you can have a # character as a password and it will work on the command line but will fail when you JSON-RPC.
{
    LOCK(cs_args);
    std::vector<std::pair<std::string, std::string>> options;
    if (!GetConfigOptions(stream, error, options)) {
        return false;
    }
    for (const std::pair<std::string, std::string>& option : options) {
        std::string strKey = std::string("-") + option.first;
        std::string strValue = option.second;
        if (InterpretNegatedOption(strKey, strValue)) {
            m_config_args[strKey].clear();
        } else {
            m_config_args[strKey].push_back(strValue);
        }
        
        if (!IsArgKnown(strKey)) {
            if (!ignore_invalid_keys) {
                error = strprintf("Invalid configuration value %s", option.first.c_str());
                return false;
            } else {
                LogPrintf("Ignoring unknown configuration value %s\n", option.first);
            }
        }
    }
    return true;
}
bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)