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
Thrown by the `BlockStdScope.host` getter in std-scope.ts. The scope holds a private `_host` that is only assigned when the `EditorHost` is mounted and `render()` has executed. Accessing `std.host` before that assignment triggers this `ValueNotExists` error — the host element does not yet exist.
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 26c515e050)
Solutions
- Move host-dependent code out of `created()` into the `rendered()` / `mounted()` lifecycle hook of the watcher or service.
- Guard with `if (this.std.host)` or use an optional accessor before invoking host APIs.
- Defer with `hostUpdated()` / `firstUpdated()` for Lit components.
- Use the `EditorLifeCycleExtension` hooks (`created`, `rendered`, `disposed`) in the correct order.
Example fix
// before: touching host in created() — runs before render
created() { this.std.host.addEventListener('keydown', this.onKey); }
// after: defer to the rendered() hook — host is assigned by then
rendered() { this.std.host.addEventListener('keydown', this.onKey); }
disposed() { this.std.host?.removeEventListener('keydown', this.onKey); } Defensive patterns
Strategy: validation
Validate before calling
// guard host access in watchers/services
function getHostSafe(std: BlockStdScope): EditorHost | null {
// `_host` is private; rely on a safe proxy if exposed, else check via try/catch
try {
return std.host;
} catch {
return null;
}
}
const host = getHostSafe(this.std);
if (host) host.addEventListener('keydown', this.onKey); Type guard
import type { BlockStdScope } from '@blocksuite/std';
import type { EditorHost } from '@blocksuite/std/view';
function stdHasHost(std: BlockStdScope): std is BlockStdScope & { host: EditorHost } {
try {
return !!std.host;
} catch {
return false;
}
} Try / catch
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
let host: EditorHost;
try {
host = this.std.host;
} catch (e) {
if (e instanceof BlockSuiteError && e.code === ErrorCode.ValueNotExists) {
// not mounted yet; defer to the rendered() hook
return;
}
throw e;
} Prevention
- Touch `std.host` only in `rendered()`/`mounted()` lifecycle hooks, never in `created()`.
- Use optional chaining and null checks before host APIs.
- Prefer `firstUpdated`/`hostUpdated` for Lit components.
When it happens
Trigger: Calling `std.host`, `std.view`, or any API that routes through `host` (e.g. `blockComponent.host`, `renderChildren`, range/sync helpers) before `EditorHost` has rendered — typically inside a `BlockService.created()` hook, an `EditorLifeCycleExtension`, or a watcher's `created()` that runs during `BlockStdScope` construction.
Common situations: Service/watcher code that touches `std.host` synchronously in `created()` instead of waiting for the `mounted`/`rendered` lifecycle; using `std.host` in a constructor; a watcher that runs before the host has connected to the DOM.
Related errors
- ErrorCode.NoRootModelError
- Blob engine is not initialized
- DatabaseBlockError
- ErrorCode.MissingViewModelError
- ReactiveProxyError
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/2cae31af4997fdab.
Report an issue: GitHub.