jquense/yup · error · Error

Yup.reach cannot resolve an array item at index: ${_part}, i

Error message

Yup.reach cannot resolve an array item at index: ${_part}, in the path: ${path}. because there is no value at that index. 

What it means

While resolving a path with an array index, reach()/getIn() checks that the actual runtime value actually has an element at that index. This Error is thrown when the index in the path is beyond the length of the current value (or the value exists but is too short).

Source

Thrown at src/util/reach.ts:35

  // root path: ''
  if (!path) return { parent, parentPath: path, schema };

  forEach(path, (_part, isBracket, isArray) => {
    let part = isBracket ? _part.slice(1, _part.length - 1) : _part;

    schema = schema.resolve({ context, parent, value });

    let isTuple = schema.type === 'tuple';
    let idx = isArray ? parseInt(part, 10) : 0;

    if (schema.innerType || isTuple) {
      if (isTuple && !isArray)
        throw new Error(
          `Yup.reach cannot implicitly index into a tuple type. the path part "${lastPartDebug}" must contain an index to the tuple element, e.g. "${lastPartDebug}[0]"`,
        );
      if (value && idx >= value.length) {
        throw new Error(
          `Yup.reach cannot resolve an array item at index: ${_part}, in the path: ${path}. ` +
            `because there is no value at that index. `,
        );
      }
      parent = value;
      value = value && value[idx];
      schema = isTuple ? schema.spec.types[idx] : schema.innerType!;
    }

    // sometimes the array index part of a path doesn't exist: "nested.arr.child"
    // in these cases the current part is the next schema and should be processed
    // in this iteration. For cases where the index signature is included this
    // check will fail and we'll handle the `child` part on the next iteration like normal
    if (!isArray) {
      if (!schema.fields || !schema.fields[part])
        throw new Error(
          `The schema does not contain the path: ${path}. ` +
            `(failed at: ${lastPartDebug} which is a type: "${schema.type}")`,

View on GitHub (pinned to ff31eee8a2)

Solutions

  1. Check the value's length before calling reach: value.items?.length > idx
  2. Guard with optional chaining and skip reach when the element is absent
  3. Use a smaller/default index or make the path length-agnostic
  4. Ensure the value passed to reach() is the fully-populated one

Example fix

// before
yup.reach(schema, 'items[3]', { items: [] }); // throws
// after
if ((data.items?.length ?? 0) > 3) yup.reach(schema, 'items[3]', data);
Defensive patterns

Strategy: validation

Validate before calling

const m = path.match(/^(.*)\[(\d+)\]$/);
if (m) {
  const arr = m[1].split('.').reduce((o, k) => o?.[k], data);
  if (!Array.isArray(arr) || Number(m[2]) >= arr.length) return undefined;
}

Type guard

function indexExists(value: unknown, idx: number): value is { length: number } & any[] {
  return Array.isArray(value) && idx < value.length;
}

Try / catch

try { return yup.reach(schema, path, value); } catch (e) { if (/no value at that index/.test(e.message)) return null; throw e; }

Prevention

When it happens

Trigger: yup.reach(schema, 'items[5]', value) where value.items has fewer than 6 elements; idx (parsed from the path part) >= value.length.

Common situations: Hardcoded indices against variable-length arrays; empty arrays from an unfinished form; paths built dynamically with a stale index after data changed.

Related errors


AI-assisted analysis of jquense/yup@ff31eee8a2 (2026-08-31). Data as JSON: /api/errors/cbc136da03f9bb93. Report an issue: GitHub.