roundcube/roundcubemail · critical · RuntimeException

incorrect response from

Error message

incorrect response from %s

What it means

During OAuth discovery, rcmail_oauth::init() fetches the provider's OpenID configuration from the well-known URI and requires an 'issuer' field. If the response is not valid discovery metadata (HTML error page, wrong URL, proxy interference, non-JSON body), json_decode yields no 'issuer' and this exception is thrown.

Solutions

  1. curl the well-known URI and verify it returns JSON containing 'issuer'.
  2. Correct the oauth 'issuer' / discovery URL in Roundcube config.
  3. Clear the discovery cache (the $key_cache entry) so a fixed endpoint is re-fetched.
  4. Check for proxies/firewalls rewriting the response and ensure the request includes required auth headers if the endpoint is protected.

Example fix

// before
$config_uri = 'https://idp.example.com/.well-known/openid-configuration'; // 404 HTML page
// after
$config_uri = 'https://idp.example.com/realms/main/.well-known/openid-configuration';
Defensive patterns

Strategy: validation

Validate before calling

$resp = file_get_contents($config_uri);
$data = json_decode($resp, true);
if (!is_array($data) || !isset($data['issuer'])) { /* abort init: bad discovery document */ }

Type guard

function isValidDiscovery($data): bool { return is_array($data) && isset($data['issuer']) && is_string($data['issuer']); }

Try / catch

try { $rcmail->oauth->init(); } catch (\RuntimeException $e) { rcube::raise_error(['message' => 'OIDC discovery failed: ' . $e->getMessage()], true, false); }

Prevention

When it happens

Trigger: discover() (called from init()) GETs {issuer}/.well-known/openid-configuration and the decoded JSON has no 'issuer' key — wrong well-known URL, IDP returning an error page, or a truncated/cached bad response.

Common situations: oauth_provider option 'issuer' typo; IDP behind a proxy returning HTML error pages; provider config endpoint moved; stale cache entry from an earlier bad discovery.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of roundcube/roundcubemail@4b54c2acfb (2026-09-14). Data as JSON: /api/errors/84ef60ece124b8bb. Report an issue: GitHub.

Appendix: source

Thrown at program/include/rcmail_oauth.php:228

        if (empty($config_uri)) {
            return;
        }

        $key_cache = 'discovery.' . md5($config_uri);

        try {
            $data = $this->cache ? $this->cache->get($key_cache) : null;

            if ($data === null) {
                // Caveat: if .well-known URL is not answering it will break login display (will not display the button)
                $response = $this->http_client->get($config_uri);
                $data = json_decode($response->getBody(), true);

                $this->log_debug('fetched OIDC config: %s', json_encode($data));

                // sanity check
                if (!isset($data['issuer'])) {
                    throw new \RuntimeException('incorrect response from %s', $config_uri);
                }

                // cache answer
                if ($this->cache) {
                    $this->cache->set($key_cache, $data);
                }
            }

            // map discovery to our options
            foreach (self::$config_mapper as $config_key => $options_key) {
                if (!empty($data[$config_key])) {
                    $this->options[$options_key] = $data[$config_key];
                }
            }

            // check if pkce method is supported by this server
            if ($this->options['pkce'] && isset($data['code_challenge_methods_supported']) && is_array($data['code_challenge_methods_supported'])) {
                if (!in_array($this->options['pkce'], $data['code_challenge_methods_supported'])) {

View on GitHub (pinned to 4b54c2acfb)