jquense/yup · error · TypeError

either `then:` or `otherwise:` is required for `when()` cond

Error message

either `then:` or `otherwise:` is required for `when()` conditions

What it means

Condition.fromOptions() builds a conditional schema branch from a `when()` call, and requires at least one of `then` or `otherwise` to know what schema to yield when `is` matches or fails. If neither is supplied there is nothing to resolve, so yup throws this TypeError immediately at condition-construction time. It is a configuration mistake, caught before any validation runs.

Source

Thrown at src/Condition.ts:31

  then?: (schema: T) => ISchema<any>;
  otherwise?: (schema: T) => ISchema<any>;
};

export type ResolveOptions<TContext = any> = {
  value?: any;
  parent?: any;
  context?: TContext;
};

class Condition<TIn extends ISchema<any, any> = ISchema<any, any>> {
  fn: ConditionBuilder<TIn>;

  static fromOptions<TIn extends ISchema<any, any>>(
    refs: Reference[],
    config: ConditionConfig<TIn>,
  ) {
    if (!config.then && !config.otherwise)
      throw new TypeError(
        'either `then:` or `otherwise:` is required for `when()` conditions',
      );

    let { is, then, otherwise } = config;

    let check =
      typeof is === 'function'
        ? is
        : (...values: any[]) => values.every((value) => value === is);

    return new Condition<TIn>(refs, (values, schema: any) => {
      let branch = check(...values) ? then : otherwise;

      return branch?.(schema) ?? schema;
    });
  }

  constructor(

View on GitHub (pinned to ff31eee8a2)

Solutions

  1. Provide at least one branch: add `then:` or `otherwise:` to the when() options object.
  2. If a branch should be a no-op, set it explicitly, e.g. otherwise: (s) => s or then: yup.string().notRequired().
  3. Check that the config object is not being spread with undefined keys overwriting real ones.

Example fix

// before
schema.when('age', { is: (v) => v >= 18 })
// after
schema.when('age', { is: (v) => v >= 18, then: (s) => s.required(), otherwise: (s) => s.notRequired() })
Defensive patterns

Strategy: validation

Validate before calling

function validateWhenConfig(cfg) {
  if (cfg && cfg.is != null && !cfg.then && !cfg.otherwise)
    throw new TypeError('when() needs a `then` or `otherwise` branch');
}

Type guard

const hasBranch = (c) => c != null && (typeof c.then !== 'undefined' || typeof c.otherwise !== 'undefined');

Prevention

When it happens

Trigger: Calling schema.when('other', { is: true }) (any config object with `is` but neither `then` nor `otherwise`), or when(refs, { is, then: undefined, otherwise: undefined }) explicitly.

Common situations: Building dynamic config objects where then/otherwise are spread from optional values that turn out undefined; copy-pasting a when() example and deleting one branch; generating conditions programmatically with optional branches.

Related errors


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