JamesNK/Newtonsoft.Json · error · JsonException
Step cannot be zero.
Error message
Step cannot be zero.
What it means
Thrown unconditionally by ArraySliceFilter.ExecuteFilter when the slice Step property equals zero. A slice step of zero would create an infinite loop, so the filter rejects it up front at ArraySliceFilter.cs:16-18 regardless of any ErrorWhenNoMatch setting. It originates from a JSONPath slice expression of the form [start:end:step] where step is 0.
Source
Thrown at Src/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs:18
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class ArraySliceFilter : PathFilter
{
public int? Start { get; set; }
public int? End { get; set; }
public int? Step { get; set; }
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{
if (Step == 0)
{
throw new JsonException("Step cannot be zero.");
}
foreach (JToken t in current)
{
if (t is JArray a)
{
// set defaults for null arguments
int stepCount = Step ?? 1;
int startIndex = Start ?? ((stepCount > 0) ? 0 : a.Count - 1);
int stopIndex = End ?? ((stepCount > 0) ? a.Count : -1);
// start from the end of the list if start is negative
if (Start < 0)
{
startIndex = a.Count + startIndex;
}
// end from the start of the list if stop is negativeView on GitHub (pinned to 4f73e74372)
Solutions
- Ensure the step portion of any slice expression is a non-zero integer (positive or negative).
- If the step is computed dynamically, guard it: skip the slice or use step 1 when the computed step is 0.
- Remove the explicit :0 from the slice and rely on the default step of 1.
Example fix
// before
token.SelectTokens($"$.data[{start}:{end}:{step}]");
// after
var safeStep = step == 0 ? 1 : step;
token.SelectTokens($"$.data[{start}:{end}:{safeStep}]"); Defensive patterns
Strategy: validation
Validate before calling
// Never let step be zero in a slice expression
int safeStep = (step == 0) ? 1 : step;
string path = $"$.data[{start}:{end}:{safeStep}"; Try / catch
try
{
token.SelectTokens($"$.data[{start}:{end}:{step}]");
}
catch (JsonException ex) when (ex.Message.Contains("Step cannot be zero"))
{
// retry with default step of 1
token.SelectTokens($"$.data[{start}:{end}:1]");
} Prevention
- Treat a computed step of zero as a no-op or substitute 1.
- Validate any user-supplied slice parameters before embedding them in a path.
- Unit-test slice generation against boundary inputs including step 0.
When it happens
Trigger: Using a JSONPath slice with an explicit zero step, e.g. token.SelectTokens("$.data[1:5:0]"), which is parsed into ArraySliceFilter { Start=1, End=5, Step=0 }. The check fires before any token is examined, so it throws even on valid arrays.
Common situations: Building a slice expression dynamically where the step value is computed and can legitimately be zero; copying a Python-style slice but passing a zero stride; off-by-one in a computed step variable.
Related errors
- Array slice of {0} to {1} returned no results.
- Array slice is not valid on {0}.
- Unexpected merge array handling when merging JSON.
- arrayIndex is less than 0.
- arrayIndex is equal to or greater than the length of array.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/b827f581c91326b9.
Report an issue: GitHub.