toeverything/AFFiNE · error · Error

Blob engine is not initialized

Error message

Blob engine is not initialized

What it means

ResourceController manages blob/file/image fetching via a BlobEngine. The engine is optional and is wired in through setEngine(). The blob() method throws 'Blob engine is not initialized' if blob() is invoked before setEngine() has been called.

Source

Thrown at blocksuite/affine/components/src/resource/resource.ts:166

        }

        this.updateState({ ...state, uploading, downloading, errorMessage });
      });

      return () => subscription.unsubscribe();
    });
  }

  async blob() {
    const blobId = this.blobId$.peek();
    if (!blobId) return null;

    let blob: Blob | null = null;
    let errorMessage: string | null = null;

    try {
      if (!this.engine) {
        throw new Error('Blob engine is not initialized');
      }

      blob = (await this.engine.get(blobId)) ?? null;

      if (!blob) errorMessage = `${this.kind} not found`;
    } catch (err) {
      console.error(err);
      errorMessage = `Failed to retrieve ${this.kind}`;
    }

    if (errorMessage) this.updateState({ errorMessage });

    return blob;
  }

  async createUrlWith(type?: string) {
    let blob = await this.blob();
    if (!blob) return null;

View on GitHub (pinned to 26c515e050)

Solutions

  1. Always call `controller.setEngine(blobEngine)` before invoking blob().
  2. Defer blob() until the engine is available, e.g. subscribe to the engine-ready signal first.
  3. In tests, inject a mock BlobEngine via setEngine().

Example fix

// before
const ctrl = new ResourceController(blobId$);
await ctrl.blob(); // throws

// after
const ctrl = new ResourceController(blobId$).setEngine(blobEngine);
await ctrl.blob();
Defensive patterns

Strategy: type-guard

Validate before calling

if (!controller.engine) { /* wait for setEngine or return placeholder */ }

Type guard

const hasEngine = (c: ResourceController): boolean => Boolean((c as any).engine);

Prevention

When it happens

Trigger: Constructing `new ResourceController(blobId$)` and calling `.blob()` without first chaining `.setEngine(engine)`. Happens when the controller is used before the sync/blob infrastructure is ready.

Common situations: Component lifecycle races where a resource viewer renders before the editor's BlobEngine is registered; integration tests that create a ResourceController in isolation.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/dca6f1a2c8a3d3a8. Report an issue: GitHub.