toeverything/AFFiNE · error · BlockSuiteError
ValueNotExists
ValueNotExists
Error message
The overlay constructor '${this.name}' should have a static 'overlayName' property. What it means
Thrown by Overlay.setup (static DI hook) when the Overlay subclass has not overridden the static 'overlayName' property (it defaults to ''). The overlayName is used to build OverlayIdentifier(this.overlayName) for DI resolution; an empty name makes the overlay unidentifiable. Error code ValueNotExists. This is a registration-time developer error, raised during editor extension setup.
Source
Thrown at blocksuite/affine/blocks/surface/src/renderer/overlay.ts:27
import type { RoughCanvas } from '../utils/rough/canvas.js';
import type { CanvasRenderer } from './canvas-renderer.js';
/**
* An overlay is a layer covered on top of elements,
* can be used for rendering non-CRDT state indicators.
*/
export abstract class Overlay extends Extension {
static overlayName: string = '';
protected _renderer: CanvasRenderer | null = null;
constructor(protected gfx: GfxController) {
super();
}
static override setup(di: Container): void {
if (!this.overlayName) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
`The overlay constructor '${this.name}' should have a static 'overlayName' property.`
);
}
di.addImpl(OverlayIdentifier(this.overlayName), this, [
GfxControllerIdentifier,
]);
}
clear() {
this.refresh();
}
dispose() {}
refresh() {
if (this._renderer) {View on GitHub (pinned to 26c515e050)
Solutions
- Declare a unique static overlayName on every Overlay subclass: `static override overlayName = 'my-overlay';`.
- Add a compile-time/test check that imports each Overlay subclass and asserts Subclass.overlayName is a non-empty string.
- Names are DI keys — keep them stable across versions and avoid collisions with built-in overlays.
Example fix
// before
class MyOverlay extends Overlay {
// no overlayName -> setup throws ValueNotExists
render(ctx, rc) { ... }
}
// after
class MyOverlay extends Overlay {
static override overlayName = 'my-overlay';
render(ctx, rc) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
import { Overlay } from '@blocksuite/affine-block-surface';
// assert at module load / in a test:
if (typeof MyOverlay.overlayName !== 'string' || !MyOverlay.overlayName) {
throw new Error('MyOverlay must define static overlayName');
} Type guard
function hasOverlayName(Ctor) {
return typeof Ctor.overlayName === 'string' && Ctor.overlayName.length > 0;
} Prevention
- Always declare `static override overlayName = '...'` on Overlay subclasses.
- Keep overlayName stable and collision-free across versions.
- Add a unit test asserting each Overlay subclass has a non-empty static overlayName.
When it happens
Trigger: Authoring a custom Overlay subclass (a canvas layer drawn on top of elements, e.g. selection handles, alignment guides) and registering it without setting `static overlayName = '...'`. The framework calls setup(di) at init and throws.
Common situations: New overlay written by following an example that omitted overlayName; refactor that moved the field; subclassing Overlay indirectly and forgetting the static field; collision-free naming not enforced so a developer skips it.
Related errors
- ValueNotExists
- ValueNotExists
- ErrorCode.SelectionError
- ErrorCode.ValueNotExists
- ErrorCode.ModelCRUDError
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/6c8efc28bf236a5b.
Report an issue: GitHub.