toeverything/AFFiNE · error · BlockSuiteError
ErrorCode.DefaultRuntimeError
ErrorCode.DefaultRuntimeError
Error message
Property ${propName} is required to ${instance.constructor.name}. What it means
Thrown by `validatePropTypes` inside the `@requiredProperties` decorator (required.ts). When a LitElement decorated with `@requiredProperties({...})` calls `connectedCallback`, each declared property is checked; if any is `undefined`, this error fires naming the missing property and component class. It is a compile-time-like runtime contract: the consumer forgot to bind a required property.
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 26c515e050)
Solutions
- Pass the named property before the element connects: `<my-block .model=${model} .store=${store}></my-block>`.
- If the property is genuinely optional, remove it from the `@requiredProperties` map or change it to a validator that permits `undefined`.
- Ensure parent templates do not render the component until all required data is non-undefined.
Example fix
// before: required prop not bound
@requiredProperties({ model: PropTypes.object })
class MyBlock extends LitElement {}
html`<my-block></my-block>`
// after: bind the prop before connect
html`<my-block .model=${model}></my-block>` Defensive patterns
Strategy: validation
Validate before calling
// before rendering a @requiredProperties-decorated component, ensure props are set
function hasRequiredProps(
props: Record<string, unknown>,
required: string[]
): boolean {
return required.every(k => props[k] !== undefined);
}
const required = ['model', 'store'];
if (hasRequiredProps({ model, store }, required)) {
render(html`<my-block .model=${model} .store=${store}></my-block>`, container);
} Type guard
function hasAllRequired<T extends object>(obj: T, keys: Array<keyof T>): obj is T {
return keys.every(k => obj[k] !== undefined);
} Try / catch
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
try {
container.appendChild(myBlock); // triggers connectedCallback -> validatePropTypes
} catch (e) {
if (e instanceof BlockSuiteError && e.code === ErrorCode.DefaultRuntimeError) {
console.error('Missing required property:', e.message);
}
} Prevention
- Bind all properties declared in @requiredProperties before the element connects.
- Treat the decorator map as the source of truth for required bindings.
- Add unit tests that mount the component with each prop omitted to catch regressions.
When it happens
Trigger: A `@requiredProperties`-decorated block/component is mounted (connected) without one of the declared properties being set — e.g. `<my-block>` rendered without `.model` or `.store`.
Common situations: Forgetting to pass a required property/attribute when composing a block; conditional rendering that yields a block before its props are ready; refactoring a component and adding a new required prop without updating call sites.
Related errors
- Failed to read image size
- ErrorCode.MissingViewModelError
- Invalid key for: ${key}
- SchemaValidateError
- bad_request
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/f52d383e8367c42b.
Report an issue: GitHub.