jquense/yup · error · Error

Yup.reach cannot implicitly index into a tuple type. the pat

Error message

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]"

What it means

When reach()/getIn() traverses a path into a tuple schema, each path part must carry an explicit array index because tuples have heterogeneous, positional element types. This Error is thrown when a tuple is encountered but the current path part has no [index] bracket.

Source

Thrown at src/util/reach.ts:31

  parent: any;
  parentPath: string;
} {
  let parent: any, lastPart: string, lastPartDebug: string;

  // 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) {

View on GitHub (pinned to ff31eee8a2)

Solutions

  1. Append an index to the path part: 'myTuple[0]'
  2. Change the schema field from tuple() back to array() if positional types aren't needed
  3. Use schema.at()/get on the tuple schema directly instead of reach

Example fix

// before
yup.reach(schema, 'user.coords');
// after
yup.reach(schema, 'user.coords[0]');
Defensive patterns

Strategy: validation

Validate before calling

function pathHasTupleIndex(path) {
  return path.split('.').every(p => !p.startsWith('coords') || /\[\d+\]$/.test(p));
}

Type guard

function hasTupleIndex(part: string): boolean {
  return /\[\d+\]$/.test(part);
}

Try / catch

try { return yup.reach(schema, path); } catch (e) { if (/implicitly index into a tuple/.test(e.message)) return yup.reach(schema, path + '[0]'); throw e; }

Prevention

When it happens

Trigger: yup.reach(tupleSchema, 'myTuple') or 'nested.myTuple' where myTuple is a tuple — the part must be 'myTuple[0]' to select an element.

Common situations: Reusing plain-object paths against schemas converted to tuples; forgetting bracket syntax when tuple types were introduced in a schema refactor (yup.array() -> yup.tuple()).

Related errors


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