toeverything/AFFiNE · error · BlockSuiteError

ErrorCode.ValueNotExists

ErrorCode.ValueNotExists

Error message

Host is not ready to use, the `render` method should be called first

What it means

BlockStdScope.host throws ErrorCode.ValueNotExists until std.render() has been called, because render() is what creates the EditorHost element and assigns this._host (std-scope.ts:152-162). Any code reaching for std.host before that point — e.g. inside the created() lifecycle hook, a service constructor, or a standalone std used for headless work — hits this error. It is an initialization-order guard, not corruption.

Solutions

  1. Call and use the result of std.render() (or mount the standard editor container, which does it for you) before touching std.host.
  2. Move host-dependent logic into the rendered()/mounted() lifecycle hooks of an EditorLifeCycleExtension/LifeCycleWatcher.
  3. For headless/store-only work, use the Store API directly instead of std.host.
  4. Guard with getOptional-style checks or 'host' in try/catch when std may be unrendered.

Example fix

// before
class MyWatcher extends LifeCycleWatcher {
  created() { this.std.host.addEventListener('keydown', ...); }
}

// after
created() { /* no DOM yet */ }
rendered() { this.std.host.addEventListener('keydown', ...); }
Defensive patterns

Strategy: validation

Validate before calling

// Before touching std.host, ensure render happened:
const host = std.render(); // idempotent pattern: call render once, reuse element
if (!host.isConnected) document.body.append(host);

Try / catch

import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
try {
  std.host.focus();
} catch (e) {
  if (e instanceof BlockSuiteError && e.code === ErrorCode.ValueNotExists) {
    // not rendered yet — schedule for after render
  } else throw e;
}

Prevention

When it happens

Trigger: Accessing std.host (directly or via helpers that use it) inside a LifeCycleWatcher's created() hook, an extension's setup/constructor, or before appending the editor to the DOM; building a BlockStdScope for headless operations (snapshot/job work) and touching UI-only APIs.

Common situations: Custom extensions or commands that grab std.host at construction time instead of in mounted()/rendered(); using @blocksuite/std programmatically without the <editor-container> wrapper; upgrading BlockSuite versions where older code accessed host earlier than the new lifecycle allows.

Related errors


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

Appendix: source

Thrown at blocksuite/framework/std/src/scope/std-scope.ts:98

  get command() {
    return this.get(CommandManager);
  }

  get event() {
    return this.get(UIEventDispatcher);
  }

  get get() {
    return this.provider.get.bind(this.provider);
  }

  get getOptional() {
    return this.provider.getOptional.bind(this.provider);
  }

  get host() {
    if (!this._host) {
      throw new BlockSuiteError(
        ErrorCode.ValueNotExists,
        'Host is not ready to use, the `render` method should be called first'
      );
    }

    return this._host;
  }

  get range() {
    return this.get(RangeManager);
  }

  get selection() {
    return this.get(StoreSelectionExtension);
  }

  get view() {
    return this.get(ViewStore);

View on GitHub (pinned to b4c8548c09)