Skip to content

IndexOutOfRangeException: Index was outside the bounds of the array. at NRedisStack.Search.Document.Load #352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ruwentos opened this issue Dec 10, 2024 · 5 comments · Fixed by #357

Comments

@ruwentos
Copy link

NRedisStack Version: 0.13.0

Redis Stack Version: 2.8.16

Description: We got an 'Index was outside the bounds of the array' exception at NRedisStack.Search.Document.Load. This happend while we searched Redis with a query through SearchCommandsAsync.SearchAsync(string indexName, Query q).

I can test the static function NRedisStack.Search.Document.Load and will get this exception every time the parameter RedisValue[]? fields contains an uneven count of items.
So first I thought this would be a flaw in your code. But then I wrote a test that mimics the situation where the exception occurred and I'm not able to reproduce this exception.
What I see is that your code depends on what comes out of await _db.ExecuteAsync(SearchCommandBuilder.Search(indexName, q)) in your SearchCommandsAsync function:

public async Task<SearchResult> SearchAsync(string indexName, Query q)
{
    if (q.dialect == null && defaultDialect != null)
    {
        q.Dialect((int)defaultDialect);
    }

    return (await _db.ExecuteAsync(SearchCommandBuilder.Search(indexName, q))).ToSearchResult(q);
}

My questions:

  1. Have you ever experienced/heard about that the RedisResult object was shaped so that your code through an exception?
  2. Can you think of a cause of this?
  3. Do you consider to change your code that it could handle the situation without an exception?

kind regards

Swen

@chaimtevel
Copy link

Hi,

I'm having a similar situation. I haven't verified this 100% but as per the docs the results can include missing documents if a ttl is set in some scenarios.

@chaimtevel
Copy link

chaimtevel commented Dec 20, 2024

I spent a bit of time debugging and the exception is occurring here.

In my scenario the fields array only has a single empty element (which I think is due to have that null value mentioned in the redis docs) causing this line to throw this exception:

ret[fieldName] = fields[i + 1];

@atakavci
Copy link
Collaborator

hey @ruwentos @chaimtevel,

i understand this exception shows up arbitrarily and we don't have the exact steps to reproduce it, is that correct ?

@chaimtevel
Copy link

For me it was not occurring regularly, but when it does happen it happens fairly consistently till the bad data clears out.

If I recall correctly the return data that was causing this was something along these lines:

Command:

FT.Search resident_queue_idx * FILTER didSuccessfullyProcess 0 0 FILTER queueType 1 1 FILTER attempts 0 10 SORTBY requestTimestamp DESC LIMIT 0 3 DIALECT 3

Results:

1) "228"
2) "queue_name:prefix-name-167036"
3) 1) null

If I can replicate then I'll post what the data actually looked like.

Thanks!

@atakavci
Copy link
Collaborator

atakavci commented Dec 26, 2024

hey @ruwentos @chaimtevel , i built a test case(below) to experiment on the behaviour.
looks like we got it in the aggregated exceptions in searchTask.Exception

let me work on it a bit more to tailor the right behavior in Load; this needs to be handled and search result should be handed over to the caller BUT!!.. but either we need a proper way to say something is wrong with this individual doc or we need to trim it from results. Not exactly sure TBH. May be we should check what other libraries do..

    [Fact]
    public void TestDocumentLoad_Issue352()
    {
        IDatabase db = redisFixture.Redis.GetDatabase();
        db.Execute("FLUSHALL");
        var ft = db.FT();

        Schema sc = new Schema().AddTextField("first", 1.0).AddTextField("last", 1.0).AddNumericField("age");
        Assert.True(ft.Create(index, FTCreateParams.CreateParams(), sc));

        db.HashSet("student:1111", new HashEntry[] { new("first", "Joe"), new("last", "Dod"), new("age", 18) });

        Assert.True(db.KeyExpire("student:1111", TimeSpan.FromMilliseconds(500)));

        Boolean cancelled = false;
        Task searchTask = Task.Run(() =>
        {
            for (int i = 0; i < 100000; i++)
            {
                SearchResult result = ft.Search(index, new Query());
                if (cancelled) break;
            }
        });
        Task.WhenAny(searchTask, Task.Delay(2000)).GetAwaiter().GetResult();

        Assert.Null(searchTask.Exception);
        cancelled = true;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants