toeverything/AFFiNE · error · BlockSuiteError

ValueNotExists

ValueNotExists

Error message

property ${propertyId} not found

What it means

The base Component class (parent of Service, Store, Entity, Scope) gets its framework provider and props from a module-level CONSTRUCTOR_CONTEXT that is only populated while the DI container runs a component factory (via withContext). Constructing any Component subclass outside that synchronous window leaves CONSTRUCTOR_CONTEXT.current.provider undefined, so the constructor aborts immediately. This guarantees every component is born with a backing provider (framework, eventBus, DI) instead of existing half-initialized.

Solutions

  1. Never instantiate Component subclasses yourself: register with framework.service(MyService, [Deps]) / framework.impl(Identifier, MyService) and obtain instances via provider.get(MyService), provider.createEntity(...)
  2. When registering with a custom factory, accept the resolver argument and resolve dependencies inside it; better, pass the class + deps array so dependenciesToFactory constructs it within provider context
  3. In tests, build a minimal Framework (new Framework()), register the unit under test plus its dependencies, and instantiate through framework.provider().get(...)

Example fix

// before
const s = new MyService(dep); // throws: no provider context

// after
const fw = new Framework();
fw.service(MyService, [MyDep]); // container constructs it in context
const s = fw.provider().get(MyService);
Defensive patterns

Strategy: validation

Validate before calling

null

Type guard

null

Prevention

When it happens

Trigger: Calling `new MyService(...)` directly in app code or tests; writing a custom factory like `framework.impl(Identifier, () => new MyService())` — a plain arrow factory runs outside withContext; constructing a Component subclass inside an async continuation (Promise.then) that escaped the factory call.

Common situations: Unit tests that construct services manually to skip Framework setup; refactoring a POJO that was previously `new`-ed into a Component subclass; passing a hand-written factory function to impl() instead of the class plus deps array, so the container never wraps construction in context.

Related errors


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

Appendix: source

Thrown at blocksuite/affine/blocks/data-view/src/data-source.ts:104

    this.workspace.slots.docListUpdated.subscribe(() => {
      this.workspace.docs.forEach(doc => {
        if (!this.docDisposeMap.has(doc.id)) {
          this.listenToDoc(doc.getStore());
        }
      });
      this.docDisposeMap.forEach((_, id) => {
        if (!this.workspace.docs.has(id)) {
          this.docDisposeMap.get(id)?.();
          this.docDisposeMap.delete(id);
        }
      });
    });
  }

  private getProperty(propertyId: string) {
    const property = this.meta.properties.find(v => v.key === propertyId);
    if (!property) {
      throw new BlockSuiteError(
        BlockSuiteError.ErrorCode.ValueNotExists,
        `property ${propertyId} not found`
      );
    }
    return property;
  }

  private newColumnName() {
    let i = 1;
    while (
      this.block.props.columns.some(column => column.name === `Column ${i}`)
    ) {
      i++;
    }
    return `Column ${i}`;
  }

  cellValueChange(rowId: string, propertyId: string, value: unknown): void {

View on GitHub (pinned to b4c8548c09)