[2026-05-22T08:36:44-04:00] vufind.DEBUG: VuFindSearch\Backend\Solr\Connector: Query fl=%2A&wt=json&json.nl=arrarr&q=id%3A%22ir-20.500.14135-1377%22 [2026-05-22T08:36:44-04:00] vufind.DEBUG: VuFindSearch\Backend\Solr\Connector: => GET http://localhost:8983/solr/biblio/select?fl=%2A&wt=json&json.nl=arrarr&q=id%3A%22ir-20.500.14135-1377%22 [2026-05-22T08:36:44-04:00] vufind.CRITICAL: VuFindSearch\Backend\Exception\BackendException : Problem connecting to Solr. at /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php line 399 ; Laminas\Http\Client\Adapter\Exception\RuntimeException : Unable to connect to localhost:8983 . Error #0: stream_socket_client(): Unable to connect to localhost:8983 (Connection refused) ; ErrorException : stream_socket_client(): Unable to connect to localhost:8983 (Connection refused) Server Context: Array ( [USER] => apache [HOME] => /usr/share/httpd [SCRIPT_NAME] => /index.php [REQUEST_URI] => /Channels/Record?id=ir-20.500.14135-1377&lng=es&source=Solr [QUERY_STRING] => id=ir-20.500.14135-1377&lng=es&source=Solr [REQUEST_METHOD] => GET [SERVER_PROTOCOL] => HTTP/1.1 [GATEWAY_INTERFACE] => CGI/1.1 [REDIRECT_QUERY_STRING] => id=ir-20.500.14135-1377&lng=es&source=Solr [REDIRECT_URL] => /Channels/Record [REMOTE_PORT] => 36856 [SCRIPT_FILENAME] => /usr/local/vufind/public/index.php [SERVER_ADMIN] => root@localhost [CONTEXT_DOCUMENT_ROOT] => /usr/local/vufind/public [CONTEXT_PREFIX] => [REQUEST_SCHEME] => https [DOCUMENT_ROOT] => /usr/local/vufind/public [REMOTE_ADDR] => 216.73.217.10 [SERVER_PORT] => 443 [SERVER_ADDR] => 172.35.11.108 [SERVER_NAME] => buscador.riep.dev.app.rnp.br [SERVER_SOFTWARE] => Apache/2.4.62 (Oracle Linux Server) OpenSSL/3.2.2 [SERVER_SIGNATURE] => [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin [HTTP_X_FORWARDED_PORT] => 443 [HTTP_X_FORWARDED_PROTO] => https [HTTP_HOST] => buscador.riep.dev.app.rnp.br [HTTP_ACCEPT_ENCODING] => gzip, br, zstd, deflate [HTTP_COOKIE] => VUFIND_SESSION=s261hbe51hrbafr87lrc4pr39j; ui=snd5; language=es [HTTP_USER_AGENT] => Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com) [HTTP_ACCEPT] => */* [proxy-nokeepalive] => 1 [SSL_TLS_SNI] => buscador.riep.dev.app.rnp.br [HTTPS] => on [VUFIND_LOCAL_DIR] => /usr/local/vufind/local [VUFIND_ENV] => development [UNIQUE_ID] => ahBN3I7_h7IvfYxUx8OejAAAAMo [REDIRECT_STATUS] => 200 [REDIRECT_SSL_TLS_SNI] => buscador.riep.dev.app.rnp.br [REDIRECT_HTTPS] => on [REDIRECT_VUFIND_LOCAL_DIR] => /usr/local/vufind/local [REDIRECT_VUFIND_ENV] => development [REDIRECT_UNIQUE_ID] => ahBN3I7_h7IvfYxUx8OejAAAAMo [FCGI_ROLE] => RESPONDER [PHP_SELF] => /index.php [REQUEST_TIME_FLOAT] => 1779453404.3257 [REQUEST_TIME] => 1779453404 ) Backtrace: /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php line 457 - class = VuFindSearch\Backend\Solr\Connector, function = forceToBackendException, args: none. /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php line 326 - class = VuFindSearch\Backend\Solr\Connector, function = trySolrUrls, args: none. /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php line 207 - class = VuFindSearch\Backend\Solr\Connector, function = query, args: none. /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php line 267 - class = VuFindSearch\Backend\Solr\Connector, function = retrieve, args: none. unlisted file line unlisted - class = VuFindSearch\Backend\Solr\Backend, function = retrieve, args: none. /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Command/CallMethodCommand.php line 137 - function = call_user_func, args: none. /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Service.php line 106 - class = VuFindSearch\Command\CallMethodCommand, function = execute, args: none. /usr/local/vufind/module/VuFind/src/VuFind/Record/Loader.php line 137 - class = VuFindSearch\Service, function = invoke, args: none. /usr/local/vufind/module/VuFind/src/VuFind/ChannelProvider/ChannelLoader.php line 287 - class = VuFind\Record\Loader, function = load, args: none. /usr/local/vufind/module/VuFind/src/VuFind/Controller/ChannelsController.php line 93 - class = VuFind\ChannelProvider\ChannelLoader, function = getRecordContext, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php line 72 - class = VuFind\Controller\ChannelsController, function = recordAction, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 320 - class = Laminas\Mvc\Controller\AbstractActionController, function = onDispatch, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 178 - class = Laminas\EventManager\EventManager, function = triggerListeners, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php line 105 - class = Laminas\EventManager\EventManager, function = triggerEventUntil, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/DispatchListener.php line 117 - class = Laminas\Mvc\Controller\AbstractController, function = dispatch, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 320 - class = Laminas\Mvc\DispatchListener, function = onDispatch, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 178 - class = Laminas\EventManager\EventManager, function = triggerListeners, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/Application.php line 319 - class = Laminas\EventManager\EventManager, function = triggerEventUntil, args: none. /usr/local/vufind/public/index.php line 23 - class = Laminas\Mvc\Application, function = run, args: none. Whoops! There was an error.
VuFindSearch \ Backend \ Exception \ BackendException
Problem connecting to Solr.
Previous exceptions
  • Unable to connect to localhost:8983 . Error #0: stream_socket_client(): Unable to connect to localhost:8983 (Connection refused) (0)
  • stream_socket_client(): Unable to connect to localhost:8983 (Connection refused) (0)
VuFindSearch\Backend\Exception\BackendException thrown with message "Problem connecting to Solr." Stacktrace: #26 VuFindSearch\Backend\Exception\BackendException in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:399 #25 VuFindSearch\Backend\Solr\Connector:forceToBackendException in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:457 #24 Laminas\Http\Client\Adapter\Exception\RuntimeException in /usr/local/vufind/vendor/laminas/laminas-http/src/Client/Adapter/Socket.php:335 #23 ErrorException in /usr/local/vufind/vendor/laminas/laminas-http/src/Client/Adapter/Socket.php:323 #22 stream_socket_client in /usr/local/vufind/vendor/laminas/laminas-http/src/Client/Adapter/Socket.php:323 #21 Laminas\Http\Client\Adapter\Socket:connect in /usr/local/vufind/vendor/laminas/laminas-http/src/Client.php:1463 #20 Laminas\Http\Client:doRequest in /usr/local/vufind/vendor/laminas/laminas-http/src/Client.php:963 #19 Laminas\Http\Client:send in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:491 #18 VuFindSearch\Backend\Solr\Connector:send in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:442 #17 VuFindSearch\Backend\Solr\Connector:trySolrUrls in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:326 #16 VuFindSearch\Backend\Solr\Connector:query in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:207 #15 VuFindSearch\Backend\Solr\Connector:retrieve in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php:267 #14 VuFindSearch\Backend\Solr\Backend:retrieve in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Command/CallMethodCommand.php:137 #13 call_user_func in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Command/CallMethodCommand.php:137 #12 VuFindSearch\Command\CallMethodCommand:execute in /usr/local/vufind/module/VuFindSearch/src/VuFindSearch/Service.php:106 #11 VuFindSearch\Service:invoke in /usr/local/vufind/module/VuFind/src/VuFind/Record/Loader.php:137 #10 VuFind\Record\Loader:load in /usr/local/vufind/module/VuFind/src/VuFind/ChannelProvider/ChannelLoader.php:287 #9 VuFind\ChannelProvider\ChannelLoader:getRecordContext in /usr/local/vufind/module/VuFind/src/VuFind/Controller/ChannelsController.php:93 #8 VuFind\Controller\ChannelsController:recordAction in /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php:72 #7 Laminas\Mvc\Controller\AbstractActionController:onDispatch in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:320 #6 Laminas\EventManager\EventManager:triggerListeners in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:178 #5 Laminas\EventManager\EventManager:triggerEventUntil in /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php:105 #4 Laminas\Mvc\Controller\AbstractController:dispatch in /usr/local/vufind/vendor/laminas/laminas-mvc/src/DispatchListener.php:117 #3 Laminas\Mvc\DispatchListener:onDispatch in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:320 #2 Laminas\EventManager\EventManager:triggerListeners in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:178 #1 Laminas\EventManager\EventManager:triggerEventUntil in /usr/local/vufind/vendor/laminas/laminas-mvc/src/Application.php:319 #0 Laminas\Mvc\Application:run in /usr/local/vufind/public/index.php:23
26
VuFindSearch\Backend\Exception\BackendException
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:399
25
VuFindSearch\Backend\Solr\Connector forceToBackendException
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:457
24
Laminas\Http\Client\Adapter\Exception\RuntimeException
/vendor/laminas/laminas-http/src/Client/Adapter/Socket.php:335
23
ErrorException
/vendor/laminas/laminas-http/src/Client/Adapter/Socket.php:323
22
stream_socket_client
/vendor/laminas/laminas-http/src/Client/Adapter/Socket.php:323
21
Laminas\Http\Client\Adapter\Socket connect
/vendor/laminas/laminas-http/src/Client.php:1463
20
Laminas\Http\Client doRequest
/vendor/laminas/laminas-http/src/Client.php:963
19
Laminas\Http\Client send
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:491
18
VuFindSearch\Backend\Solr\Connector send
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:442
17
VuFindSearch\Backend\Solr\Connector trySolrUrls
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:326
16
VuFindSearch\Backend\Solr\Connector query
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php:207
15
VuFindSearch\Backend\Solr\Connector retrieve
/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php:267
14
VuFindSearch\Backend\Solr\Backend retrieve
/module/VuFindSearch/src/VuFindSearch/Command/CallMethodCommand.php:137
13
call_user_func
/module/VuFindSearch/src/VuFindSearch/Command/CallMethodCommand.php:137
12
VuFindSearch\Command\CallMethodCommand execute
/module/VuFindSearch/src/VuFindSearch/Service.php:106
11
VuFindSearch\Service invoke
/module/VuFind/src/VuFind/Record/Loader.php:137
10
VuFind\Record\Loader load
/module/VuFind/src/VuFind/ChannelProvider/ChannelLoader.php:287
9
VuFind\ChannelProvider\ChannelLoader getRecordContext
/module/VuFind/src/VuFind/Controller/ChannelsController.php:93
8
VuFind\Controller\ChannelsController recordAction
/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php:72
7
Laminas\Mvc\Controller\AbstractActionController onDispatch
/vendor/laminas/laminas-eventmanager/src/EventManager.php:320
6
Laminas\EventManager\EventManager triggerListeners
/vendor/laminas/laminas-eventmanager/src/EventManager.php:178
5
Laminas\EventManager\EventManager triggerEventUntil
/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php:105
4
Laminas\Mvc\Controller\AbstractController dispatch
/vendor/laminas/laminas-mvc/src/DispatchListener.php:117
3
Laminas\Mvc\DispatchListener onDispatch
/vendor/laminas/laminas-eventmanager/src/EventManager.php:320
2
Laminas\EventManager\EventManager triggerListeners
/vendor/laminas/laminas-eventmanager/src/EventManager.php:178
1
Laminas\EventManager\EventManager triggerEventUntil
/vendor/laminas/laminas-mvc/src/Application.php:319
0
Laminas\Mvc\Application run
/public/index.php:23
    /**
     * If an unexpected exception type was received, wrap it in a generic
     * BackendException to standardize upstream handling.
     *
     * @param \Exception $ex Exception
     *
     * @return \Exception
     */
    protected function forceToBackendException($ex)
    {
        // Don't wrap specific backend exceptions....
        if (
            $ex instanceof RemoteErrorException
            || $ex instanceof RequestErrorException
            || $ex instanceof HttpErrorException
        ) {
            return $ex;
        }
        return
            new BackendException('Problem connecting to Solr.', $ex->getCode(), $ex);
    }
 
    /**
     * Try all Solr URLs until we find one that works (or throw an exception).
     *
     * @param string    $method    HTTP method to use
     * @param string    $urlSuffix Suffix to append to all URLs tried
     * @param ?callable $callback  Callback to configure client (null for none)
     * @param bool      $cacheable Whether the request is cacheable
     *
     * @return string Response body
     *
     * @throws RemoteErrorException  SOLR signaled a server error (HTTP 5xx)
     * @throws RequestErrorException SOLR signaled a client error (HTTP 4xx)
     */
    protected function trySolrUrls(
        $method,
        $urlSuffix,
        $callback = null,
        bool $cacheable = false
Arguments
  1. "Problem connecting to Solr."
    
                    return $result;
                }
            }
            try {
                $result = $this->send($client);
                if ($cacheKey) {
                    $this->putCachedData($cacheKey, $result);
                }
                return $result;
            } catch (\Exception $ex) {
                if ($this->isRethrowableSolrException($ex)) {
                    throw $this->forceToBackendException($ex);
                }
                $exception = $ex;
            }
        }
 
        // If we got this far, everything failed -- throw a BackendException with
        // the most recent exception caught above set as the previous exception.
        throw $this->forceToBackendException($exception);
    }
 
    /**
     * Extract the Solr core from the connector's URL.
     *
     * @return string
     */
    public function getCore(): string
    {
        $url = rtrim($this->getUrl(), '/');
        $parts = explode('/', $url);
        return array_pop($parts);
    }
 
    /**
     * Send request the SOLR and return the response.
     *
     * @param HttpClient $client Prepared HTTP client
     *
     * @return string Response body
                throw new AdapterException\InvalidArgumentException(sprintf(
                    'integer or numeric string expected, got %s',
                    gettype($connectTimeout)
                ));
            }
 
            ErrorHandler::start();
            $this->socket = stream_socket_client(
                $host . ':' . $port,
                $errno,
                $errstr,
                (int) $connectTimeout,
                $flags,
                $context
            );
            $error        = ErrorHandler::stop();
 
            if (! $this->socket) {
                $this->close();
                throw new AdapterException\RuntimeException(
                    sprintf(
                        'Unable to connect to %s:%d%s',
                        $host,
                        $port,
                        $error ? ' . Error #' . $error->getCode() . ': ' . $error->getMessage() : ''
                    ),
                    0,
                    $error
                );
            }
 
            // Set the stream timeout
            if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
                throw new AdapterException\RuntimeException('Unable to set the connection timeout');
            }
 
            if ($secure || $this->config['sslusecontext']) {
                if ($this->setSslCryptoMethod) {
                    try {
                        $this->enableCryptoTransport($this->config['ssltransport'], $this->socket, $host);
Arguments
  1. "Unable to connect to localhost:8983 . Error #0: stream_socket_client(): Unable to connect to localhost:8983 (Connection refused)"
    
Exception message: Unable to connect to localhost:8983 . Error #0: stream_socket_client(): Unable to connect to localhost:8983 (Connection refused)
            $flags = STREAM_CLIENT_CONNECT;
            if ($this->config['persistent']) {
                $flags |= STREAM_CLIENT_PERSISTENT;
            }
 
            if (isset($this->config['connecttimeout'])) {
                $connectTimeout = $this->config['connecttimeout'];
            } else {
                $connectTimeout = $this->config['timeout'];
            }
 
            if ($connectTimeout !== null && ! is_numeric($connectTimeout)) {
                throw new AdapterException\InvalidArgumentException(sprintf(
                    'integer or numeric string expected, got %s',
                    gettype($connectTimeout)
                ));
            }
 
            ErrorHandler::start();
            $this->socket = stream_socket_client(
                $host . ':' . $port,
                $errno,
                $errstr,
                (int) $connectTimeout,
                $flags,
                $context
            );
            $error        = ErrorHandler::stop();
 
            if (! $this->socket) {
                $this->close();
                throw new AdapterException\RuntimeException(
                    sprintf(
                        'Unable to connect to %s:%d%s',
                        $host,
                        $port,
                        $error ? ' . Error #' . $error->getCode() . ': ' . $error->getMessage() : ''
                    ),
                    0,
                    $error
Arguments
  1. "stream_socket_client(): Unable to connect to localhost:8983 (Connection refused)"
    
Exception message: stream_socket_client(): Unable to connect to localhost:8983 (Connection refused)
            $flags = STREAM_CLIENT_CONNECT;
            if ($this->config['persistent']) {
                $flags |= STREAM_CLIENT_PERSISTENT;
            }
 
            if (isset($this->config['connecttimeout'])) {
                $connectTimeout = $this->config['connecttimeout'];
            } else {
                $connectTimeout = $this->config['timeout'];
            }
 
            if ($connectTimeout !== null && ! is_numeric($connectTimeout)) {
                throw new AdapterException\InvalidArgumentException(sprintf(
                    'integer or numeric string expected, got %s',
                    gettype($connectTimeout)
                ));
            }
 
            ErrorHandler::start();
            $this->socket = stream_socket_client(
                $host . ':' . $port,
                $errno,
                $errstr,
                (int) $connectTimeout,
                $flags,
                $context
            );
            $error        = ErrorHandler::stop();
 
            if (! $this->socket) {
                $this->close();
                throw new AdapterException\RuntimeException(
                    sprintf(
                        'Unable to connect to %s:%d%s',
                        $host,
                        $port,
                        $error ? ' . Error #' . $error->getCode() . ': ' . $error->getMessage() : ''
                    ),
                    0,
                    $error
        }
 
        return $parameters;
    }
 
    /**
     * Separating this from send method allows subclasses to wrap
     * the interaction with the adapter
     *
     * @param string $method
     * @param  bool $secure
     * @param array $headers
     * @param string $body
     * @return string the raw response
     * @throws Exception\RuntimeException
     */
    protected function doRequest(Http $uri, $method, $secure = false, $headers = [], $body = '')
    {
        // Open the connection, send the request and read the response
        $this->adapter->connect($uri->getHost(), $uri->getPort(), $secure);
 
        if ($this->config['outputstream']) {
            if ($this->adapter instanceof Client\Adapter\StreamInterface) {
                $this->streamHandle = $this->openTempStream();
                $this->adapter->setOutputStream($this->streamHandle);
            } else {
                throw new Exception\RuntimeException('Adapter does not support streaming');
            }
        }
        // HTTP connection
        $this->lastRawRequest = $this->adapter->write(
            $method,
            $uri,
            $this->config['httpversion'],
            $headers,
            $body
        );
 
        return $this->adapter->read();
    }
            // headers
            $headers = $this->prepareHeaders($body, $uri);
 
            $secure = $uri->getScheme() === 'https';
 
            // cookies
            $cookie = $this->prepareCookies($uri->getHost(), $uri->getPath(), $secure);
            if ($cookie->getFieldValue()) {
                $headers['Cookie'] = $cookie->getFieldValue();
            }
 
            // check that adapter supports streaming before using it
            if (is_resource($body) && ! $adapter instanceof Client\Adapter\StreamInterface) {
                throw new RuntimeException('Adapter does not support streaming');
            }
 
            $this->streamHandle = null;
            // calling protected method to allow extending classes
            // to wrap the interaction with the adapter
            $response           = $this->doRequest($uri, $method, $secure, $headers, $body);
            $stream             = $this->streamHandle;
            $this->streamHandle = null;
 
            if (! $response) {
                if ($stream !== null) {
                    fclose($stream);
                }
                throw new Exception\RuntimeException('Unable to read response, or response is empty');
            }
 
            if ($this->config['storeresponse']) {
                $this->lastRawResponse = $response;
            } else {
                $this->lastRawResponse = null;
            }
 
            if ($this->config['outputstream']) {
                if ($stream === null) {
                    $stream = $this->getStream();
                    if (! is_resource($stream) && is_string($stream)) {
    /**
     * Send request the SOLR and return the response.
     *
     * @param HttpClient $client Prepared HTTP client
     *
     * @return string Response body
     *
     * @throws RemoteErrorException  SOLR signaled a server error (HTTP 5xx)
     * @throws RequestErrorException SOLR signaled a client error (HTTP 4xx)
     */
    protected function send(HttpClient $client)
    {
        $this->debug(
            sprintf('=> %s %s', $client->getMethod(), $client->getUri())
        );
 
        $this->lastUrl = $client->getUri();
 
        $time     = microtime(true);
        $response = $client->send();
        $time     = microtime(true) - $time;
 
        $this->debug(
            sprintf(
                '<= %s %s',
                $response->getStatusCode(),
                $response->getReasonPhrase()
            ),
            ['time' => $time]
        );
 
        if (!$response->isSuccess()) {
            // Return a more detailed error message for a 400 error:
            if ($response->getStatusCode() === 400) {
                $json = json_decode($response->getBody(), true);
                $msgParts = ['400', $response->getReasonPhrase()];
                if ($msg = $json['error']['msg'] ?? '') {
                    $msgParts[] = $msg;
                }
                throw new RequestErrorException(
        $exception = new \Exception('Unexpected exception.');
 
        // Loop through all base URLs and try them in turn until one works.
        $cacheKey = null;
        foreach ((array)$this->url as $base) {
            $client = ($this->clientFactory)($base . $urlSuffix);
            $client->setMethod($method);
            if (is_callable($callback)) {
                $callback($client);
            }
            // Always create the cache key from the first server, and only after any
            // callback has been called above.
            if ($cacheable && $this->cache && null === $cacheKey) {
                $cacheKey = $this->getCacheKey($client);
                if ($result = $this->getCachedData($cacheKey)) {
                    return $result;
                }
            }
            try {
                $result = $this->send($client);
                if ($cacheKey) {
                    $this->putCachedData($cacheKey, $result);
                }
                return $result;
            } catch (\Exception $ex) {
                if ($this->isRethrowableSolrException($ex)) {
                    throw $this->forceToBackendException($ex);
                }
                $exception = $ex;
            }
        }
 
        // If we got this far, everything failed -- throw a BackendException with
        // the most recent exception caught above set as the previous exception.
        throw $this->forceToBackendException($exception);
    }
 
    /**
     * Extract the Solr core from the connector's URL.
     *
     */
    public function query($handler, ParamBag $params, bool $cacheable = false)
    {
        $urlSuffix = '/' . $handler;
        $paramString = implode('&', $params->request());
        if (strlen($paramString) > self::MAX_GET_URL_LENGTH) {
            $method = Request::METHOD_POST;
            $callback = function ($client) use ($paramString): void {
                $client->setRawBody($paramString);
                $client->setEncType(HttpClient::ENC_URLENCODED);
                $client->setHeaders(['Content-Length' => strlen($paramString)]);
            };
        } else {
            $method = Request::METHOD_GET;
            $urlSuffix .= '?' . $paramString;
            $callback = null;
        }
 
        $this->debug(sprintf('Query %s', $paramString));
        return $this->trySolrUrls($method, $urlSuffix, $callback, $cacheable);
    }
 
    /**
     * Call a method with provided options for the HTTP client
     *
     * @param array  $options HTTP client options
     * @param string $method  Method to call
     * @param array  ...$args Method parameters
     *
     * @return mixed
     */
    public function callWithHttpOptions(
        array $options,
        string $method,
        ...$args
    ) {
        $reflectionMethod = new \ReflectionMethod($this, $method);
        if (!$reflectionMethod->isPublic()) {
            throw new InvalidArgumentException("Method '$method' is not public");
        }
    }
 
    /**
     * Return document specified by id.
     *
     * @param string    $id     Document identifier
     * @param ?ParamBag $params Search backend parameters
     *
     * @return string
     */
    public function retrieve($id, ?ParamBag $params = null)
    {
        $params = $params ?: new ParamBag();
        $params
            ->set('q', sprintf('%s:"%s"', $this->uniqueKey, addcslashes($id, '"')));
 
        $handler = $this->map->getHandler(__FUNCTION__);
        $this->map->prepare(__FUNCTION__, $params);
 
        return $this->query($handler, $params, true);
    }
 
    /**
     * Return records similar to a given record specified by id.
     *
     * Uses MoreLikeThis Request Component or MoreLikeThis Handler
     *
     * @param string   $id     ID of given record (not currently used, but
     * retained for legacy backward compatibility / extensibility).
     * @param ParamBag $params Parameters
     *
     * @return string
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function similar($id, ParamBag $params)
    {
        $handler = $this->map->getHandler(__FUNCTION__);
        $this->map->prepare(__FUNCTION__, $params);
 
        $sort = "{$random}_random asc";
        $params->set('sort', $sort);
 
        return $this->search($query, 0, $limit, $params);
    }
 
    /**
     * Retrieve a single document.
     *
     * @param string    $id     Document identifier
     * @param ?ParamBag $params Search backend parameters
     *
     * @return RecordCollectionInterface
     */
    public function retrieve($id, ?ParamBag $params = null)
    {
        $params = $params ?: new ParamBag();
        $this->injectResponseWriter($params);
 
        $response   = $this->connector->retrieve($id, $params);
        $collection = $this->createRecordCollection($response);
        $this->injectSourceIdentifier($collection);
        return $collection;
    }
 
    /**
     * Retrieve a batch of documents.
     *
     * @param array     $ids    Array of document identifiers
     * @param ?ParamBag $params Search backend parameters
     *
     * @return RecordCollectionInterface
     */
    public function retrieveBatch($ids, ?ParamBag $params = null)
    {
        $params = $params ?: new ParamBag();
 
        // Callback function for formatting IDs:
        $formatIds = function ($i) {
            return '"' . addcslashes($i, '"') . '"';
     *
     * @return CommandInterface Command instance for method chaining
     */
    public function execute(BackendInterface $backend): CommandInterface
    {
        $this->validateBackend($backend);
        if (
            !($backend instanceof $this->interface)
            || !method_exists($this->interface, $this->method)
        ) {
            throw new BackendException(
                "$this->backendId does not support $this->method()"
            );
        }
        $args = $this->getArguments();
        if ($backend instanceof ExtraRequestDetailsInterface) {
            $backend->resetExtraRequestDetails();
        }
        $this->finalizeExecution(
            call_user_func([$backend, $this->method], ...$args)
        );
        if ($backend instanceof ExtraRequestDetailsInterface) {
            $this->extraRequestDetails = $backend->getExtraRequestDetails();
        }
        return $this;
    }
}
 
     *
     * @return CommandInterface Command instance for method chaining
     */
    public function execute(BackendInterface $backend): CommandInterface
    {
        $this->validateBackend($backend);
        if (
            !($backend instanceof $this->interface)
            || !method_exists($this->interface, $this->method)
        ) {
            throw new BackendException(
                "$this->backendId does not support $this->method()"
            );
        }
        $args = $this->getArguments();
        if ($backend instanceof ExtraRequestDetailsInterface) {
            $backend->resetExtraRequestDetails();
        }
        $this->finalizeExecution(
            call_user_func([$backend, $this->method], ...$args)
        );
        if ($backend instanceof ExtraRequestDetailsInterface) {
            $this->extraRequestDetails = $backend->getExtraRequestDetails();
        }
        return $this;
    }
}
 
    }
 
    /**
     * Invoke a command.
     *
     * @param CommandInterface $command Command
     *
     * @return CommandInterface
     */
    public function invoke(CommandInterface $command)
    {
        // The backend instance is no longer added as an event parameter.
        // All other legacy event parameters are accessible via the command object.
        $args = ['command' => $command];
 
        $backend = $this->resolve($command->getTargetIdentifier(), $args);
 
        $this->triggerPre($this, $args);
        try {
            $command->execute($backend);
        } catch (BackendException $e) {
            $args['error'] = $e;
            $this->triggerError($this, $args);
            throw $e;
        }
        $this->triggerPost($this, $args);
 
        return $command;
    }
 
    /**
     * Resolve a backend.
     *
     * @param string            $backendId Backend name
     * @param array|ArrayAccess $args      Service function arguments
     *
     * @return BackendInterface
     *
     * @throws Exception\RuntimeException Unable to resolve backend
     */
     * @return \VuFind\RecordDriver\AbstractBase
     */
    public function load(
        $id,
        $source = DEFAULT_SEARCH_BACKEND,
        $tolerateMissing = false,
        ?ParamBag $params = null
    ) {
        if (null !== $id && '' !== $id) {
            $results = [];
            if (
                null !== $this->recordCache
                && $this->recordCache->isPrimary($source)
            ) {
                $results = $this->recordCache->lookup($id, $source);
            }
            if (empty($results)) {
                try {
                    $command = new RetrieveCommand($source, $id, $params);
                    $results = $this->searchService->invoke($command)
                        ->getResult()->getRecords();
                } catch (BackendException $e) {
                    if (!$tolerateMissing) {
                        throw $e;
                    }
                }
            }
            if (
                empty($results) && null !== $this->recordCache
                && $this->recordCache->isFallback($source)
            ) {
                $results = $this->recordCache->lookup($id, $source);
                if (!empty($results)) {
                    $results[0]->setExtraDetail('cached_record', true);
                }
            }
 
            if (!empty($results)) {
                return $results[0];
            }
    /**
     * Generates channels for a record.
     *
     * @param string $recordId       Record ID to load
     * @param string $token          Channel token (optional, used for AJAX fetching)
     * @param string $activeChannel  Channel being requested (optional, used w/ token)
     * @param string $source         Search backend to use
     * @param array  $configSections Prioritized list of configuration sections to check
     *
     * @return array
     */
    public function getRecordContext(
        $recordId,
        $token = null,
        $activeChannel = null,
        $source = DEFAULT_SEARCH_BACKEND,
        array $configSections = ['record']
    ) {
        // Load record:
        $driver = $this->recordLoader->load($recordId, $source);
 
        // Load appropriate channel objects:
        $providers = [];
        foreach ($configSections as $section) {
            $providers = $this->getChannelProviders($source, $section, $activeChannel);
            if (!empty($providers)) {
                break;
            }
        }
 
        // Collect details:
        $channels = [];
        foreach ($providers as $provider) {
            $channels = array_merge(
                $channels,
                $provider->getFromRecord($driver, $token)
            );
        }
 
        // Return context array:
    {
        $source = $this->params()->fromQuery('source', DEFAULT_SEARCH_BACKEND);
        $activeChannel = $this->params()->fromQuery('channelProvider');
        $token = $this->params()->fromQuery('channelToken');
        $context = $this->loader->getHomeContext($token, $activeChannel, $source);
        return $this->createViewModel($context);
    }
 
    /**
     * Generates channels for a record.
     *
     * @return \Laminas\View\Model\ViewModel
     */
    public function recordAction()
    {
        $recordId = $this->params()->fromQuery('id');
        $source = $this->params()->fromQuery('source', DEFAULT_SEARCH_BACKEND);
        $activeChannel = $this->params()->fromQuery('channelProvider');
        $token = $this->params()->fromQuery('channelToken');
        $context = $this->loader->getRecordContext($recordId, $token, $activeChannel, $source);
        return $this->createViewModel($context);
    }
 
    /**
     * Generates channels for a search.
     *
     * @return \Laminas\View\Model\ViewModel
     */
    public function searchAction()
    {
        // Send both GET and POST variables to search class:
        $request = $this->getRequest()->getQuery()->toArray()
            + $this->getRequest()->getPost()->toArray();
        $source = $this->params()->fromQuery('source', DEFAULT_SEARCH_BACKEND);
        $activeChannel = $this->params()->fromQuery('channelProvider');
        $token = $this->params()->fromQuery('channelToken');
        $context = $this->loader
            ->getSearchContext($request, $token, $activeChannel, $source);
        return $this->createViewModel($context);
    }
     */
    public function onDispatch(MvcEvent $e)
    {
        $routeMatch = $e->getRouteMatch();
        if (! $routeMatch) {
            /**
             * @todo Determine requirements for when route match is missing.
             *       Potentially allow pulling directly from request metadata?
             */
            throw new DomainException('Missing route matches; unsure how to retrieve action');
        }
 
        $action = $routeMatch->getParam('action', 'not-found');
        $method = static::getMethodFromAction($action);
 
        if (! method_exists($this, $method)) {
            $method = 'notFoundAction';
        }
 
        $actionResponse = $this->$method();
 
        $e->setResult($actionResponse);
 
        return $actionResponse;
    }
}
 
        }
 
        if ($this->sharedManager) {
            foreach ($this->sharedManager->getListeners($this->identifiers, $name) as $priority => $listeners) {
                $listOfListenersByPriority[$priority][] = $listeners;
            }
        }
 
        // Sort by priority in reverse order
        krsort($listOfListenersByPriority);
 
        // Initial value of stop propagation flag should be false
        $event->stopPropagation(false);
 
        // Execute listeners
        $responses = new ResponseCollection();
        foreach ($listOfListenersByPriority as $listOfListeners) {
            foreach ($listOfListeners as $listeners) {
                foreach ($listeners as $listener) {
                    $response = $listener($event);
                    $responses->push($response);
 
                    // If the event was asked to stop propagating, do so
                    if ($event->propagationIsStopped()) {
                        $responses->setStopped(true);
                        return $responses;
                    }
 
                    // If the result causes our validation callback to return true,
                    // stop propagation
                    if (is_callable($callback) && $callback($response)) {
                        $responses->setStopped(true);
                        return $responses;
                    }
                }
            }
        }
 
        return $responses;
    }
            $event->setParams($argv);
        }
 
        return $this->triggerListeners($event, $callback);
    }
 
    /**
     * @inheritDoc
     */
    public function triggerEvent(EventInterface $event)
    {
        return $this->triggerListeners($event);
    }
 
    /**
     * @inheritDoc
     */
    public function triggerEventUntil(callable $callback, EventInterface $event)
    {
        return $this->triggerListeners($event, $callback);
    }
 
    /**
     * @inheritDoc
     */
    public function attach($eventName, callable $listener, $priority = 1)
    {
        if (! is_string($eventName)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects a string for the event; received %s',
                __METHOD__,
                get_debug_type($eventName),
            ));
        }
 
        $this->events[$eventName][(int) $priority][0][] = $listener;
        return $listener;
    }
 
    /**
     * @events dispatch.pre, dispatch.post
     * @param  Request $request
     * @param  null|Response $response
     * @return Response|mixed
     */
    public function dispatch(Request $request, ?Response $response = null)
    {
        $this->request = $request;
        if (! $response) {
            $response = new HttpResponse();
        }
        $this->response = $response;
 
        $e = $this->getEvent();
        $e->setName(MvcEvent::EVENT_DISPATCH);
        $e->setRequest($request);
        $e->setResponse($response);
        $e->setTarget($this);
 
        $result = $this->getEventManager()->triggerEventUntil(static fn($test): bool => $test instanceof Response, $e);
 
        if ($result->stopped()) {
            return $result->last();
        }
 
        return $e->getResult();
    }
 
    /**
     * Get request object
     *
     * @return Request
     */
    public function getRequest()
    {
        if (! $this->request) {
            $this->request = new HttpRequest();
        }
 
        return $this->request;
            );
            return $this->complete($return, $e);
        } catch (Throwable $exception) {
            $return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception);
            return $this->complete($return, $e);
        } catch (Exception $exception) {  // @TODO clean up once PHP 7 requirement is enforced
            $return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception);
            return $this->complete($return, $e);
        }
 
        if ($controller instanceof InjectApplicationEventInterface) {
            $controller->setEvent($e);
        }
 
        $request  = $e->getRequest();
        $response = $application->getResponse();
        $caughtException = null;
 
        try {
            $return = $controller->dispatch($request, $response);
        } catch (Throwable $ex) {
            $caughtException = $ex;
        } catch (Exception $ex) {  // @TODO clean up once PHP 7 requirement is enforced
            $caughtException = $ex;
        }
 
        if ($caughtException !== null) {
            $e->setName(MvcEvent::EVENT_DISPATCH_ERROR);
            $e->setError($application::ERROR_EXCEPTION);
            $e->setController($controllerName);
            $e->setControllerClass($controller::class);
            $e->setParam('exception', $caughtException);
 
            $return = $application->getEventManager()->triggerEvent($e)->last();
            if (! $return) {
                $return = $e->getResult();
            }
        }
 
        return $this->complete($return, $e);
        }
 
        if ($this->sharedManager) {
            foreach ($this->sharedManager->getListeners($this->identifiers, $name) as $priority => $listeners) {
                $listOfListenersByPriority[$priority][] = $listeners;
            }
        }
 
        // Sort by priority in reverse order
        krsort($listOfListenersByPriority);
 
        // Initial value of stop propagation flag should be false
        $event->stopPropagation(false);
 
        // Execute listeners
        $responses = new ResponseCollection();
        foreach ($listOfListenersByPriority as $listOfListeners) {
            foreach ($listOfListeners as $listeners) {
                foreach ($listeners as $listener) {
                    $response = $listener($event);
                    $responses->push($response);
 
                    // If the event was asked to stop propagating, do so
                    if ($event->propagationIsStopped()) {
                        $responses->setStopped(true);
                        return $responses;
                    }
 
                    // If the result causes our validation callback to return true,
                    // stop propagation
                    if (is_callable($callback) && $callback($response)) {
                        $responses->setStopped(true);
                        return $responses;
                    }
                }
            }
        }
 
        return $responses;
    }
            $event->setParams($argv);
        }
 
        return $this->triggerListeners($event, $callback);
    }
 
    /**
     * @inheritDoc
     */
    public function triggerEvent(EventInterface $event)
    {
        return $this->triggerListeners($event);
    }
 
    /**
     * @inheritDoc
     */
    public function triggerEventUntil(callable $callback, EventInterface $event)
    {
        return $this->triggerListeners($event, $callback);
    }
 
    /**
     * @inheritDoc
     */
    public function attach($eventName, callable $listener, $priority = 1)
    {
        if (! is_string($eventName)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects a string for the event; received %s',
                __METHOD__,
                get_debug_type($eventName),
            ));
        }
 
        $this->events[$eventName][(int) $priority][0][] = $listener;
        return $listener;
    }
 
    /**
            $response = $result->last();
            if ($response instanceof ResponseInterface) {
                $event->setName(MvcEvent::EVENT_FINISH);
                $event->setTarget($this);
                $event->setResponse($response);
                $event->stopPropagation(false); // Clear before triggering
                $events->triggerEvent($event);
                $this->response = $response;
                return $this;
            }
        }
 
        if ($event->getError()) {
            return $this->completeRequest($event);
        }
 
        // Trigger dispatch event
        $event->setName(MvcEvent::EVENT_DISPATCH);
        $event->stopPropagation(false); // Clear before triggering
        $result = $events->triggerEventUntil($shortCircuit, $event);
 
        // Complete response
        $response = $result->last();
        if ($response instanceof ResponseInterface) {
            $event->setName(MvcEvent::EVENT_FINISH);
            $event->setTarget($this);
            $event->setResponse($response);
            $event->stopPropagation(false); // Clear before triggering
            $events->triggerEvent($event);
            $this->response = $response;
            return $this;
        }
 
        $response = $this->response;
        $event->setResponse($response);
        return $this->completeRequest($event);
    }
 
    /**
     * Complete the request
$vufindProfiler = getenv('VUFIND_PROFILER_XHPROF');
if (!empty($vufindProfiler)) {
    include __DIR__ . '/../module/VuFind/functions/profiler.php';
    enableVuFindProfiling($vufindProfiler);
}
 
// Run the application!
$app = include __DIR__ . '/../config/application.php';
if (PHP_SAPI === 'cli') {
    return $app->getServiceManager()
        ->get(\VuFindConsole\ConsoleRunner::class)->run();
} else {
    // Setup remote code coverage if enabled:
    if (getenv('VUFIND_CODE_COVERAGE')) {
        $modules = $app->getServiceManager()
            ->get(\Laminas\ModuleManager\ModuleManager::class)->getModules();
        include __DIR__ . '/../module/VuFind/functions/codecoverage.php';
        setupVuFindRemoteCodeCoverage($modules);
    }
    $app->run();
}
 

Environment & details:

Key Value
id
"ir-20.500.14135-1377"
lng
"es"
source
"Solr"
empty
empty
Key Value
VUFIND_SESSION
"s261hbe51hrbafr87lrc4pr39j"
ui
"snd5"
language
"es"
Key Value
__Laminas
array:4 [
  "_REQUEST_ACCESS_TIME" => 1779453404.3425
  "_VALID" => array:1 [
    "Laminas\Session\Validator\Id" => "s261hbe51hrbafr87lrc4pr39j"
  ]
  "FlashMessenger" => array:1 [
    "EXPIRE_HOPS" => array:2 [
      "hops" => 1
      "ts" => 1779453374.2749
    ]
  ]
  "csrf" => array:1 [
    "EXPIRE" => 1779453674
  ]
]
SessionState
Laminas\Stdlib\ArrayObject {#949}
Followup
Laminas\Stdlib\ArrayObject {#947}
FlashMessenger
Laminas\Stdlib\ArrayObject {#951}
csrf
Laminas\Stdlib\ArrayObject {#953}
SessionHelper
Laminas\Stdlib\ArrayObject {#954}
Key Value
USER
"apache"
HOME
"/usr/share/httpd"
SCRIPT_NAME
"/index.php"
REQUEST_URI
"/Channels/Record?id=ir-20.500.14135-1377&lng=es&source=Solr"
QUERY_STRING
"id=ir-20.500.14135-1377&lng=es&source=Solr"
REQUEST_METHOD
"GET"
SERVER_PROTOCOL
"HTTP/1.1"
GATEWAY_INTERFACE
"CGI/1.1"
REDIRECT_QUERY_STRING
"id=ir-20.500.14135-1377&lng=es&source=Solr"
REDIRECT_URL
"/Channels/Record"
REMOTE_PORT
"36856"
SCRIPT_FILENAME
"/usr/local/vufind/public/index.php"
SERVER_ADMIN
"root@localhost"
CONTEXT_DOCUMENT_ROOT
"/usr/local/vufind/public"
CONTEXT_PREFIX
""
REQUEST_SCHEME
"https"
DOCUMENT_ROOT
"/usr/local/vufind/public"
REMOTE_ADDR
"216.73.217.10"
SERVER_PORT
"443"
SERVER_ADDR
"172.35.11.108"
SERVER_NAME
"buscador.riep.dev.app.rnp.br"
SERVER_SOFTWARE
"Apache/2.4.62 (Oracle Linux Server) OpenSSL/3.2.2"
SERVER_SIGNATURE
""
PATH
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
HTTP_X_FORWARDED_PORT
"443"
HTTP_X_FORWARDED_PROTO
"https"
HTTP_HOST
"buscador.riep.dev.app.rnp.br"
HTTP_ACCEPT_ENCODING
"gzip, br, zstd, deflate"
HTTP_COOKIE
"VUFIND_SESSION=s261hbe51hrbafr87lrc4pr39j; ui=snd5; language=es"
HTTP_USER_AGENT
"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)"
HTTP_ACCEPT
"*/*"
proxy-nokeepalive
"1"
SSL_TLS_SNI
"buscador.riep.dev.app.rnp.br"
HTTPS
"on"
VUFIND_LOCAL_DIR
"/usr/local/vufind/local"
VUFIND_ENV
"development"
UNIQUE_ID
"ahBN3I7_h7IvfYxUx8OejAAAAMo"
REDIRECT_STATUS
"200"
REDIRECT_SSL_TLS_SNI
"buscador.riep.dev.app.rnp.br"
REDIRECT_HTTPS
"on"
REDIRECT_VUFIND_LOCAL_DIR
"/usr/local/vufind/local"
REDIRECT_VUFIND_ENV
"development"
REDIRECT_UNIQUE_ID
"ahBN3I7_h7IvfYxUx8OejAAAAMo"
FCGI_ROLE
"RESPONDER"
PHP_SELF
"/index.php"
REQUEST_TIME_FLOAT
1779453404.3257
REQUEST_TIME
1779453404
empty
0. Whoops\Handler\PrettyPageHandler