"Invalid NEST response built from a unsuccessful () low level call on POST" - elasticsearch

The following code works most of the time but sometimes it throws an exception with this message:
Invalid NEST response built from a unsuccessful () low level call on POST: /queries2020-09/_search?typed_keys=true
var response = await client.SearchAsync<LogEntry>(s => s
.Query(q => q
.Bool(b => b
.Must(m => m.DateRange(r => r.Field(l => l.DateTimeUTC)
.GreaterThanOrEquals(new DateMathExpression(since))),
m => m.Term(term)
)))
.Aggregations(a => a
.Sum("total-cost", descriptor => descriptor
.Field(f => f.Cost)
.Missing(1)))
.Size(0));
if (!response.IsValid)
{
throw new Exception("Elasticsearch response error. " + response.ToString());
}
This seems to be a very generic message that pops up a lot on Q&A websites. How do I debug it to see the root cause?
Using NEST 7.6.1.

It may be better to write the debug information out rather than .ToString()
if (!response.IsValid)
{
throw new Exception("Elasticsearch response error. " + response.DebugInformation);
}
The debug information includes the audit trail and details about an error/exception, if there is one. It's a convenience method for collecting the pertinent information available on IResponse in a human readable form.
If a response is always checked for validity and an exception thrown, you may want to set ThrowExceptions() on ConnectionSettings to throw when an error occurs.

Related

How to run some code in an RxJS chain given there were no errors

I am trying to find a way to run some code only if there was no error in a given rxjs chain. Consider the following, is there something like the artificial NO_ERROR_OCCURED_RUN_HAPPY_PATH_CODE operator in rxjs?
private wrap(obs: Observable<any>): Observable<any> {
return of(1).pipe(
tap(() => this.spinner.startSpinner()),
mergeMap(() =>
obs.pipe(
NO_ERROR_OCCURED_RUN_HAPPY_PATH_CODE(() => this.generic_success_popup()),
catchError(this.handleError),
)
),
finalize(() => this.spinner.stopSpinner())
);
}
Basically almost all operator will be invoke if no error is thrown along the pipe, apart from finalize
obs.pipe(
tap(_=>console.log('no error, will run'),
// throw some error
map(_=>throwError('some error'),
finalize(_=>console.log('will be called when there is error or upon observable complete')),
tap(_=>console.log('this will not run')),
catchError(this.handleError),
)

Elastic Search search_phase_execution_exception Reason: "all shards failed"

ES Query is as following :
var searchResponse = client.Search<ItemSearch>(s => s
.Query(q => q
.MultiMatch(mm => mm
.Query(searchQuery)
.Type(TextQueryType.BestFields)
.Fields(f => f.Field(p => p.Description).Field(p=>p.Comment).Field(p => p.CommentSmall)
.Field(p => p.DisplaySequence).Field(p => p.ImageUrl).Field(p => p.ItemBrandDescription)
.Field(p => p.ItemBrandSequence).Field(p => p.ItemCode)
.Field(p => p.ItemGroupID).Field(p => p.ItemGroupSpecification).Field(p => p.ItemMaximumOrderAmount)
.Field(p => p.ItemMinimumOrderAmount).Field(p => p.ItemSpecsDescription).Field(p => p.ItemSupplierCode)
.Field(p => p.PackSize).Field(p => p.PriceUnit).Field(p => p.Sequence).Field(p => p.Stock).Field(p => p.StockToday).Field(p => p.StockTomorrow)
.Field(p => p.SupplierCode).Field(p => p.UOM).Field(p => p.UOMTypeID).Field(p => p.UOMTypeDescription)
).Query(searchQuery)
)
));
getting Following error, Can anyone please help me out?
ServerError:ServerError: 400Type: search_phase_execution_exception Reason: "all shards failed"
DebugInformation:Invalid NEST response built from a unsuccessful low level call on POST: /myindex2-solvi/itemsearch/_search
# Audit trail of this API call:
- [1] BadResponse: Node: http://localhost:9200/ Took: 00:00:00.2664112
# ServerError: ServerError: 400Type: search_phase_execution_exception Reason: "all shards failed"
# OriginalException: System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at Elasticsearch.Net.HttpConnection.Request[TReturn](RequestData requestData)
# Request:
<Request stream not captured or already read to completion by serializer. Set DisableDirectStreaming() on ConnectionSettings to force it to be set on the response.>
# Response:
<Response stream not captured or already read to completion by serializer. Set DisableDirectStreaming() on ConnectionSettings to force it to be set on the response.>
IsValid:False
OriginalException:System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at Elasticsearch.Net.HttpConnection.Request[TReturn](RequestData requestData)
Solution if you have multiple websites.
Go to System > Store > Configuration > Catalog > Catalog Search > Elasticsearch Index Prefix
Change the prefix for each store
Save Settings, Clear Cache, and Run index again
Another Official Solution is
Base on the bug filed in my previous reply, I modified the following file to fix the search problem.
./vendor/magento/module-elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldType/Converter.php
private const ES_DATA_TYPE_DOUBLE = 'double';
--> private const ES_DATA_TYPE_FLOAT = 'float';
self::INTERNAL_DATA_TYPE_FLOAT => self::ES_DATA_TYPE_DOUBLE,
---> self::INTERNAL_DATA_TYPE_FLOAT => self::ES_DATA_TYPE_FLOAT,

Elasticsearch NEST 5.x Search Query that is built dynamically

I have the following query that I build piecemeal/dynamically using "&=". Elasticsearch 5.x and Nest 5.x.
QueryContainer qfilter = null;
qfilter = Query<ClassEL>.Term(m => m.OrderID, iOrderID);
qfilter &= Query<ClassEL>
.Range(r => r
.Field(f => f.Distance)
.GreaterThan(100))
&&
.Query<ClassEL>.Term(t => t.Active, true);
var searchDes = new SearchDescriptor<ClassEL>()
.From(0)
.Size(10)
.Query(qfilter); <===== *** ERROR HERE ***
In Visual Studio, it shows the following error message tip:
Error: Cannot convert from 'Nest.QueryContainer' to 'System.Func<Nest.QueryContainerDescriptor<ClassEL>, Nest.QueryContainer>'
The problem is I can't get the searchDescriptor to accept the query I built. Examples online show Search + Query rolled into one which differs from what I'm trying to accomplish. Below is common example that I want to avoid:
var response = client.Search<Tweet>(s => s
.From(0)
.Size(10)
.Query(q =>
q.Term(t => t.User, "kimchy")
|| q.Match(mq => mq.Field(f => f.User).Query("nest"))
)
);
EDIT: Using the Andrey's answer works just fine. A problem arises however when I try to get the results back from the search query:
List<ClassViewEL> listDocuments = response.Documents.ToList();
Visual Studio doesn't highlight it as an error immediately, but during compile time has a problem:
error CS0570:
'Nest.ISearchResponse.Documents' is
not supported by the language
Debugging and choosing to IGNORE the above error works fine, the code executes just as expected no problems. However the compile time error will prevent code deployments. How can this error be fixed?
Solution to EDIT: One of my dependencies in my projects (Newtonsoft.Json.dll) were targeting an older version causing the error to appear. Cleaning the solution and rebuilding fixes it.
You should use Func<SearchDescriptor<ClassEL>, ISearchRequest> or pass descriptor in separate method. For example:
var queryContainer = Query<ClassEL>.Term(x => x.Field(f => f.FirstName).Value("FirstName"));
queryContainer &= Query<ClassEL>.Term(x => x.Field(f => f.LastName).Value("LastName"));
Func<SearchDescriptor<ClassEL>, ISearchRequest> searchFunc = searchDescriptor => searchDescriptor
.Index("indexName")
.Query(q => queryContainer);
var response = _client.Search<ClassEL>(searchFunc);
or like this
ISearchRequest ExecuteQuery(SearchDescriptor<ClassEL> searchDescriptor, QueryContainer queryContainer)
{
return searchDescriptor.Index("indexName")
.Query(q => queryContainer);
}
public void GetResults()
{
var queryContainer = Query<ClassEL>.Term(x => x.Field(f => f.FirstName).Value("FirstName"));
queryContainer &= Query<ClassEL>.Term(x => x.Field(f => f.LastName).Value("LastName"));
var response = _client.Search<ClassEL>(s => ExecuteQuery(s, queryContainer));
}

Codeception, unable to simulate ajax behavior

I can't replicate ajax calls via codeception.
For example:
$I->sendAjaxPostRequest('login/verify', array('name' => 'name', 'password' => 'password'));
$I->seeResponseIsJson();
Will not raise any errors. But in the other hand, if I do the following:
$I->sendAjaxPostRequest('login/verify', array('name' => 'name', 'password' => 'password'));
$I->seeResponseIsJson();
$I->seeResponseContainsJson(['login_failed' => 1]);
//or
$I->grabDataFromJsonResponse('data.login_failed');
It gives me this error:
ErrorException: Argument 2 passed to
Codeception\Module\REST::arrayHasArray() must be of the type array,
null given, called in
C:\xampp\htdocs\blog\laravel\vendor\codeception\codeception\src\Codeception\Module\REST.php
on line 485 and defined
What I understand from the error above is that seeResponseContainsJson or grabDataFromJsonResponse internally will pass a response as a second argument to arrayHasArray. But it looks like no matter what the response is always empty.
Also, if I do the following:
$I->sendAjaxPostRequest('login/verify', array('name' => 'name', 'password' => 'password'));
var_dump($I->grabResponse());
I receive this for var_dump():
object(Codeception\Maybe)#753 (3) {
["position":protected]=>
int(0)
["val":protected]=>
NULL
["assocArray":protected]=>
NULL
}
Everything else works as expected with Codeception, I'm using PhpBrowser.
I'm sure not how useful this answer is to anyone else, but I landed here whilst googling for a similar error message:
ErrorException: Argument 2 passed to Codeception\Module\REST::arrayHasArray()
must be of the type array, null given
After much hair-pulling, I discovered that some debug output from my controller (a var_dump) was causing the returned document to not be valid JSON, and using $I->seeResponseContainsJson() was therefore throwing errors internally, as the response wasn't valid JSON
So, ensure the response your controller is sending is valid JSON, and this error should go away

Magento update inventory with REST

I Followed the instruction of this page http://www.magentocommerce.com/api/rest/Resources/inventory.html#RESTAPI-Resource-StockItems-HTTPMethod-PUT-stockitems--id and I have this code:
$oauthClient->setToken($_SESSION['token'], $_SESSION['secret']);
$resourceUrl = $apiUrl.'/stockitems/429';
$productData = json_encode(array(
'qty' => 982,
'is_in_stock' => 1
));
$headers = array('Content-Type' => 'application/json');
$oauthClient->fetch($resourceUrl, $productData, OAUTH_HTTP_METHOD_POST, $headers);
print_r($oauthClient->getLastResponseInfo());
But I get the return
[message:protected] => Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)
I tried with XML like this:
$oauthClient->setToken($_SESSION['token'], $_SESSION['secret']);
$resourceUrl = $apiUrl.'/stockitems/429';
$productData = '<?xml version="1.0"?>
<magento_api>
<qty>99</qty>
</magento_api>';
$headers = array('Content-Type' => 'text/xml');
$oauthClient->fetch($resourceUrl, $productData, OAUTH_HTTP_METHOD_POST, $headers);
print_r($oauthClient->getLastResponseInfo());
and I get the error:
[message:protected] => Invalid auth/bad request (got a 405, expected HTTP/1.1 20X or a redirect)
I don't know what I'm doing wrong?
Thank you for your reply.
Another way to update item's quantity is to call the /products/:id API, method = PUT, with the following payload:
{"stock_data" : {"qty" : "123"}}
You are using POST instead of PUT. HTTP Post is used for creating items in Magento, but if you update an item (or inventory, image, whatever) by id you have to use PUT.
Make sure you assigned to your admin user REST role.
Configuring Permissions Step By Step:
System -> Web Services -> REST - Roles -> Create new role
System -> Web Services -> REST - Consumers -> Create a Consumer -> Copy Key & Secret to use in your App
System -> Permissions -> Your User -> REST Role -> Select and Save your Role

Resources