toeverything/AFFiNE · error · BlockSuiteError

ErrorCode.DefaultRuntimeError

ErrorCode.DefaultRuntimeError

Error message

Property ${propName} is required to ${instance.constructor.name}.

What it means

The @requiredProperties decorator (blocksuite/framework/std/src/view/decorators/required.ts) validates declared props each time the decorated LitElement's connectedCallback runs. If a listed property is still undefined at connect time, it throws this DefaultRuntimeError naming the property and the component class. It exists to fail fast when a block/view component is instantiated without the data it needs to render.

Solutions

  1. Pass every required property before the element connects (set properties on the instance before appending, or bind them in the Lit template).
  2. If the prop is genuinely optional, remove it from the decorator's propTypes map or give the class a default value.
  3. In tests/storybooks, construct via the standard view path or set props prior to appending to the DOM.
  4. Check the error message for the exact property name and class, then set that prop.

Example fix

// before
const el = new MyBlockComponent();
document.body.append(el); // connectedCallback fires, props still undefined
el.store = store;

// after
const el = new MyBlockComponent();
el.store = store;
el.model = model;
document.body.append(el);
Defensive patterns

Strategy: validation

Validate before calling

// Before appending a decorated component, assert required props:
const el = new MyBlockComponent();
el.store = store;
el.model = model;
const missing = ['store', 'model'].filter(k => (el as any)[k] === undefined);
if (missing.length === 0) document.body.append(el);

Type guard

function hasRequiredProps(el: LitElement, props: string[]): boolean {
  return props.every(p => (el as any)[p] !== undefined);
}

Prevention

When it happens

Trigger: Mounting a component decorated with @requiredProperties({ model: PropTypes.object, ... }) without setting every listed property first — e.g. creating the element imperatively via document.createElement and appending it before assigning props, or rendering it in a template without binding an attribute.

Common situations: Using BlockSuite view components outside the standard view registry (storybooks, previews, tests); forgetting a newly added required prop in a subclass; Lit property timing issues where attributes are set after connect.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/f52d383e8367c42b. Report an issue: GitHub.

Appendix: source

Thrown at blocksuite/framework/std/src/view/decorators/required.ts:31

  instanceOf: (expectedClass: Constructor) => (value: unknown) =>
    value instanceof expectedClass,
  arrayOf: (validator: ValidatorFunction) => (value: unknown) =>
    Array.isArray(value) && value.every(validator),
  recordOf: (validator: ValidatorFunction) => (value: unknown) => {
    if (typeof value !== 'object' || value === null) return false;
    return Object.values(value).every(validator);
  },
  of: (validator: ValidatorFunction) => (value: unknown) => validator(value),
};

function validatePropTypes<T extends InstanceType<Constructor>>(
  instance: T,
  propTypes: Record<string, ValidatorFunction>
) {
  for (const [propName, validator] of Object.entries(propTypes)) {
    const key = propName as keyof T;
    if (instance[key] === undefined) {
      throw new BlockSuiteError(
        ErrorCode.DefaultRuntimeError,
        `Property ${propName} is required to ${instance.constructor.name}.`
      );
    }
    if (validator && !validator(instance[key])) {
      throw new BlockSuiteError(
        ErrorCode.DefaultRuntimeError,
        `Property ${propName} is invalid to ${instance.constructor.name}.`
      );
    }
  }
}

export function requiredProperties(
  propTypes: Record<string, ValidatorFunction>
) {
  return function (constructor: Constructor<LitElement>) {
    const connectedCallback = constructor.prototype.connectedCallback;

View on GitHub (pinned to b4c8548c09)